Berk Akademi
Birebir ders başvurusu Ücretsiz ön görüşme Ana Sayfa

ClassNotFoundException ve NoClassDefFoundError Farkı

classmethodnotfoundexception-noclassdeffounderror-farki
Bu yazıda neler var?
  1. İki hata neden benzer görünür, fakat aynı şey değildir?
  2. ClassNotFoundException nasıl oluşur ve nereden başlanır?
  3. NoClassDefFoundError hangi çalışma zamanı koşullarını gösterir?
  4. Derleme zamanı ile çalışma zamanını tek teşhis akışında birleştirin
  5. JAR, paketleme çıktısı ve gerçek başlatma classpath’i nasıl doğrulanır?
  6. İki mini senaryo ile farkı uygulamalı teşhis edin
  7. Son kontrol: Hangi hatada hangi sırayı izlemelisiniz?
  8. Sık Sorulan Sorular

ClassNotFoundException ile NoClassDefFoundError aynı temel probleme, yani JVM’in ihtiyaç duyduğu bir sınıfı kullanamamasına işaret edebilir; ancak oluştuğu bağlam ve teşhis yaklaşımı farklıdır. ClassNotFoundException çoğunlukla uygulama bir sınıfı adıyla dinamik olarak yüklemeye çalıştığında oluşan bir exception’dır. NoClassDefFoundError ise derlenmiş kod çalışma sırasında daha önce bilinen bir sınıfa erişemediğinde veya bir sınıfın başlatılması başarısız olduktan sonra o sınıf yeniden kullanılmaya çalışıldığında görülen bir error’dur.

Bu nedenle iki hatayı yalnızca “JAR dosyası eksik” diye yorumlamak doğru değildir. Yanlış binary sınıf adı, package uyumsuzluğu, eksik runtime dependency, hatalı classpath, dependency scope farkı ve başarısız bir static başlatma işlemi benzer görünen fakat farklı kanıtlar üretir.

İki hata neden benzer görünür, fakat aynı şey değildir?

JVM bir sınıfı kullanmadan önce onu yükleme, bağlama ve gerektiğinde başlatma süreçlerinden geçirir. Yükleme aşamasında sınıfın binary adıyla eşleşen tanım aranır. Bağlama sırasında sınıfın yapısı, üst sınıfları ve sembolik referansları doğrulanır. Başlatma aşamasında ise static alan başlatıcıları ve static bloklar çalıştırılır. Bu aşamalar uygulamanın tek bir satırında görünmez; sınıfın ilk kez nerede ve nasıl kullanıldığına bağlı olarak farklı zamanlarda gerçekleşebilir.

ClassNotFoundException ile NoClassDefFoundError arasındaki en pratik ayrım şudur:

Hata Tipi Tipik bağlam İlk bakılacak kanıt
ClassNotFoundException Exception Bir sınıf adı metin olarak verilmiş ve sınıf dinamik olarak yüklenememiştir. İstenen tam binary sınıf adı ve dinamik yükleme kodu
NoClassDefFoundError Error Derlenmiş kod çalışma sırasında ihtiyaç duyduğu sınıf tanımına erişememiş veya sınıf başlatılamamıştır. İlk hata kaydı, Caused by bölümü ve gerçek runtime classpath

“Dosya bulunamadı” açıklaması bu farkı gizler. Örneğin com.example.ReportPlugin adı istenmiş olabilir; fakat kaynak dosyası şu package bildirimiyle derlenmiştir:

package com.example.plugin;

public class ReportPlugin {
}

Bu sınıfın doğru binary adı com.example.plugin.ReportPlugin olur. Dolayısıyla JAR içinde aranması gereken giriş yolu da com/example/plugin/ReportPlugin.class şeklindedir. JAR içinde sınıfın bulunması, yanlış binary ad kullanıldığı için ClassNotFoundException alınmasını engellemez. Sınıf yükleyiciler sınıfı yalnızca kısa sınıf adıyla değil, package ile birlikte oluşturulan binary ad ve ilgili class loader bağlamıyla değerlendirir.

Benzer şekilde kaynak kodu derlenmiş olabilir; fakat derleme sırasında kullanılan dependency çalışma sırasında classpath’e eklenmemişse uygulama daha sonra NoClassDefFoundError verebilir. Burada kaynak dosyasının doğru olması, JAR’ın gerçekten oluşturulması ve dependency’nin runtime scope içinde bulunması üç ayrı kontroldür.

ClassNotFoundException nasıl oluşur ve nereden başlanır?

ClassNotFoundException nasıl oluşur ve nereden başlanır?

ClassNotFoundException için tipik senaryo, uygulamanın sınıf adını bir yapılandırmadan, dosyadan veya kullanıcı girdisinden metin olarak almasıdır. Class.forName, ClassLoader.loadClass veya benzeri bir API çağrısı bu metni binary sınıf adı kabul eder. Java API dokümantasyonunda bu exception, uygulama bir sınıfı string adıyla yüklemeye çalıştığında ve belirtilen ada ait tanımı bulamadığında açıklanır.

Mini senaryo: Yanlış package adı mı, eksik dependency mi?

String className = "com.example.ReportPlugin";
Class<?> pluginClass = Class.forName(className);

Kaynak dosyası önceki örnekteki gibi package com.example.plugin; bildirimiyle derlendiyse beklenen doğru çağrı şöyledir:

String className = "com.example.plugin.ReportPlugin";
Class<?> pluginClass = Class.forName(className);

Stack trace içinde şu sınıf adını görüyorsan:

java.lang.ClassNotFoundException: com.example.ReportPlugin
    at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(...)
    at java.base/java.lang.ClassLoader.loadClass(...)
    at java.base/java.lang.Class.forName0(Native Method)

İlk kanıt, JVM’in tam olarak com.example.ReportPlugin adını aradığıdır. Bu ad kaynak dosyasındaki package ve class bildirimiyle uyuşmuyorsa önce dependency aramak yerine adı düzeltmelisin. Sınıf adı doğruysa ikinci ihtimal, sınıfı içeren JAR’ın uygulamanın gerçek çalışma classpath’inde bulunmamasıdır. Bu tür isim çözümleme ve classpath kontrollerini sistematik biçimde öğrenmek isteyenler için Java’da sınıf yükleme ve bağımlılık teşhisine odaklanan birebir çalışma yararlı bir başlangıç olabilir.

Teşhisi şu sırayla ilerlet:

  1. Hata mesajındaki tam sınıf adını oku. Büyük-küçük harf, package adı ve iç sınıf gösterimi dâhil hiçbir bölümü kısaltma.
  2. Kaynak dosyasını kontrol et. package bildirimiyle public class veya ilgili sınıf bildiriminin adını karşılaştır.
  3. Derlenmiş JAR girişini doğrula. Örneğin com.example.plugin.ReportPlugin için beklenen yol com/example/plugin/ReportPlugin.class olur.
  4. Uygulamanın gerçekten hangi classpath ile başlatıldığını bul. IDE’de görünen dependency listesiyle terminalde, betikte veya paketlenmiş uygulamada kullanılan classpath aynı olmayabilir.
  5. Dinamik yükleme koduna verilen değeri incele. Yapılandırma dosyasında kısa ad, dosya yolu, yanlış package veya görünmeyen bir boşluk bulunabilir.

JAR’ın belirli sınıfı içerip içermediğini görmek için JDK ile gelen jar aracı kullanılabilir:

jar tf uygulama.jar

Bu komut JAR arşivinin içindekiler tablosunu gösterir; burada amaç uygulamayı başlatmak değil, beklenen .class girişinin gerçekten pakete girip girmediğini kontrol etmektir. Örneğin çıktı içinde com/example/plugin/ReportPlugin.class yoksa sorun paketleme aşamasındadır. Giriş mevcut olduğu hâlde ClassNotFoundException devam ediyorsa gerçek classpath, class loader veya istenen binary ad üzerinde durmalısın. jar tf biçimi, Oracle’ın JAR içeriğini listeleme dokümantasyonunda açıklanan temel kullanımdır.

Yanlış sınıf adı ile eksik dependency’yi ayıran kısa kural: JAR içinde sınıfın yolu hiç yoksa paketleme veya dependency seçimi sorunu düşünülür. Yol JAR içinde doğru biçimde varsa fakat stack trace’te istenen ad farklıysa binary sınıf adı veya dinamik yükleme girdisi hatalıdır. JAR’da doğru giriş mevcut ve ad da doğruysa bir sonraki inceleme, uygulamanın o JAR’ı gerçekten runtime classpath’e alıp almadığıdır.

NoClassDefFoundError hangi çalışma zamanı koşullarını gösterir?

NoClassDefFoundError, genellikle derlenmiş kodun çalışma sırasında ihtiyaç duyduğu sınıf tanımına erişemediğini gösterir. API açıklamasındaki önemli ayrıntı, aranan sınıf tanımının mevcut kod derlenirken bulunmuş olabilmesi; ancak daha sonra çalışma ortamında bulunamaması veya erişilebilir olmamasıdır. Bu yüzden hata, “kod hiç derlenmedi” anlamına gelmez.

Mini senaryo: Derleme başarılı, çalışma classpath’i eksik

Bir sınıfın derlenmesi sırasında harici bir dependency kullanılmış olsun:

public class InvoicePrinter {
    public void print() {
        ExternalFormatter formatter = new ExternalFormatter();
        formatter.format();
    }
}

Derleme classpath’inde ExternalFormatter sınıfını içeren JAR bulunduğu için derleme tamamlanabilir. Fakat uygulama başlatılırken bu JAR runtime classpath’e eklenmemişse, InvoicePrinter sınıfının bağlanması veya print metodunda ilgili kod yolunun çalışması sırasında NoClassDefFoundError görülebilir. Hatanın uygulama başlar başlamaz veya yalnızca belirli bir özellik kullanıldığında ortaya çıkması, JVM’in sınıf çözümlemesini her zaman bütün sınıflar için aynı anda yapmak zorunda olmamasıyla ilişkilidir. JVM Specification, çözümlemenin daha erken veya sembolik referans kullanıldığı noktada yapılabileceğini belirtir.

Bu durumda stack trace’in en altındaki veya Caused by bölümündeki sınıf adına bak. Üstte InvoicePrinter görünse bile eksik olan sınıf çoğu zaman ExternalFormatter gibi onun dependency’sidir. Sonraki soru, bu sınıfın hangi JAR’dan gelmesi gerektiği ve o JAR’ın paketlenen çıktı ile uygulamanın başlatıldığı classpath’te gerçekten bulunup bulunmadığıdır.

Mini senaryo: Sınıf bulundu, fakat başlatılması başarısız oldu

public class BrokenConfig {
    static {
        if (true) {
            throw new IllegalStateException("Başlatma başarısız");
        }
    }

    public static String value() {
        return "hazır";
    }
}

İlk kez BrokenConfig.value() çağrıldığında sınıfın static başlatma kodu çalışır ve hata üretir. Bu ilk kayıtta ExceptionInInitializerError veya başlatma sırasında oluşan asıl exception görülebilir. JVM sınıfı hatalı durumda işaretledikten sonra aynı sınıfı yeniden başlatmaya çalışmak mümkün değildir; sonraki erişimlerde NoClassDefFoundError bağlamı oluşabilir. JLS, başlatma başarısızlığı sonrasında sınıfın “erroneous state” durumuna geçtiğini ve sonraki başlatma denemesinde NoClassDefFoundError fırlatıldığını açıklar.

Bu nedenle yalnızca son NoClassDefFoundError kaydını okumak yanıltıcı olabilir. Özellikle aynı uygulama akışında daha önceki exception kaydını, Caused by zincirini ve ilk başlatma denemesinin nedenini birlikte incelemelisin. İlk hata gerçek nedeni, sonraki NoClassDefFoundError ise bu başarısızlığın sonucu olabilir.

Hata Oluştuğu aşama Kontrol edilecek kanıt Uygulanacak düzeltme
ClassNotFoundException Dinamik sınıf adıyla yükleme Mesajdaki binary ad, package bildirimi, Class.forName veya loadClass girdisi Binary sınıf adını düzelt; ardından gerçek runtime classpath’i kontrol et
NoClassDefFoundError Bağlama, çözümleme veya çalışma sırasında dependency erişimi Caused by, eksik sınıfın ait olduğu JAR, paketleme çıktısı ve başlatma classpath’i Eksik runtime dependency’yi doğru scope ile paketle ve aynı classpath ile başlat
NoClassDefFoundError Daha önce başarısız olmuş sınıf başlatmasının ardından yeniden erişim İlk hata kaydı, ExceptionInInitializerError, static blok veya alan başlatıcısı İlk başlatma hatasının asıl nedenini düzelt; yalnızca son error mesajını yamamaya çalışma
  • İlk olarak hata türünü değil, stack trace’te adı geçen sınıfı ve hatanın ilk oluştuğu kaydı belirle.
  • ClassNotFoundException için sınıf adının nasıl üretildiğini incele.
  • NoClassDefFoundError için dependency’nin derleme classpath’inde bulunmasıyla runtime classpath’inde bulunmasının aynı şey olmadığını unutma.
  • JAR içinde doğru giriş olduğu hâlde hata sürüyorsa paketleme değil, başlatma classpath’i veya sınıf başlatma zinciri üzerinde yoğunlaş.

Derleme zamanı ile çalışma zamanını tek teşhis akışında birleştirin

Bir sınıfın derleme sırasında bulunması, uygulama çalıştırıldığında da bulunacağı anlamına gelmez. Derleyici kaynak kodunu oluştururken bir compile classpath kullanır; JVM ise uygulamayı başlatırken veya belirli bir kod yoluna girerken farklı bir runtime classpath üzerinden sınıfları yükler. Bu iki ortam arasındaki fark, derlemesi başarılı olan bir projenin çalışma zamanında ClassNotFoundException ya da NoClassDefFoundError vermesine yol açabilir.

Bu nedenle teşhisi şu karar zinciriyle yürütmek daha güvenlidir:

  1. Derleniyor mu? Hata derleme aşamasında mı, yoksa java komutundan sonra mı oluşuyor?
  2. Çalışırken hangi classpath kullanılıyor? IDE, komut satırı, betik, dağıtım paketi veya container aynı classpath’i kullanmayabilir.
  3. Bağımlılık hangi scope ya da configuration içinde? Bir kütüphane yalnızca derleme için tanımlanmışsa çalışma ortamına taşınmayabilir.
  4. Paketleme çıktısında JAR var mı? Bağımlılık çözülmüş olsa bile dağıtım klasörüne kopyalanmamış veya uygulama JAR’ının içine alınmamış olabilir.

Maven ağacını okurken doğrudan ve aktarılan bağımlılıkları ayırın

Maven’da pom.xml içindeki doğrudan bağımlılıklar, başka kütüphanelerin ihtiyaç duyduğu aktarılan bağımlılıkları da etkileyebilir. Bu nedenle yalnızca dosyada yazan birkaç satıra bakmak yeterli değildir. mvn dependency:tree örneği, projenin çözümlenen bağımlılık hiyerarşisini gösterir; böylece eksik görünen bir kütüphanenin hangi bağımlılık yolundan geldiği, farklı sürüm isteklerinin bulunup bulunmadığı ve bazı düğümlerin neden dışarıda bırakıldığı incelenebilir.

Burada amaç komutu ezberlemek değil, şu soruyu yanıtlamaktır: “Kodumun kullandığı sınıf, gerçekten bu proje için çözümlenen ağacın içinde mi ve hangi kapsamda yer alıyor?” Gerekirse belirli bir bağımlılığı daha görünür hâle getirmek için ağacı filtreleyebilir veya bağımlılık classpath’ini ayrı bir çıktı olarak inceleyebilirsin. Maven eklentisinin hedefleri, filtreleme seçenekleri ve çıktı ayrıntıları kullanılan proje yapılandırmasına göre değişebileceğinden, sorun anında projenin kullandığı Maven ve eklenti belgeleriyle karşılaştırma yapmalısın.

Gradle raporunda configuration seçmeden sonuca güvenmeyin

Gradle’da bağımlılık raporu, seçilen configuration’a göre hazırlanır. Bu nedenle compileClasspath için görünen bir bağımlılığın runtimeClasspath içinde de aynı biçimde bulunacağını varsaymak doğru değildir. Yerleşik dependencies göreviyle proje ağacı incelenebilir; belirli bir configuration seçildiğinde rapor yalnızca o bağlamdaki doğrudan ve aktarılan bağımlılıkları gösterir. Örneğin yaygın kullanım biçimi, runtime tarafını ayrıca incelemek için ./gradlew dependencies --configuration runtimeClasspath şeklindedir.

Gradle raporu okunurken özellikle compileClasspath ile runtimeClasspath başlıklarını karşılaştır. compileOnly gibi yalnızca derleme bağlamına ait bir tanım veya uygun runtime configuration’a taşınmayan bir bağımlılık, derlemenin başarılı olmasına rağmen uygulama çalışırken eksik sınıf hatası oluşturabilir. Belirli bir kütüphanenin hangi yoldan geldiğini ve sürümünün neden seçildiğini anlamak için dependencyInsight görevi de ilgili configuration ile birlikte kullanılabilir.

Bu tür ayrımları uygulamalı olarak pekiştirmek için Java ve algoritmik düşünme bilgi testleri ile yalnızca sözdizimini değil, kodun hangi aşamada neden davrandığını da sınayabilirsin.

Kısa teşhis kuralı: Derleme başarısızsa önce kaynak kodu, package bildirimini ve compile classpath’i kontrol et. Derleme başarılı, çalışma başarısızsa dependency scope/configuration, dağıtım JAR’ları ve uygulamayı başlatan gerçek classpath üzerinde yoğunlaş.

JAR, paketleme çıktısı ve gerçek başlatma classpath’i nasıl doğrulanır?

JAR, paketleme çıktısı ve gerçek başlatma classpath’i nasıl doğrulanır?

Bağımlılık ağacının doğru görünmesi tek başına yeterli kanıt değildir. Çalışan uygulamanın gerçekten hangi dosyaları gördüğünü doğrulamak için JAR içeriğini, dağıtım klasörünü ve başlatma komutunu birlikte incelemelisin.

Belirti Muhtemel aşama Kontrol edilecek kanıt Uygulanacak düzeltme
Sınıf adında package eksik veya hatalı Dinamik yükleme Hata mesajındaki tam ad ve kaynak dosyanın package bildirimi Doğru binary sınıf adını kullan
Dinamik yüklemede yanlış isim veriliyor Çalışma zamanı sınıf araması Class.forName veya loadClass parametresi Package dâhil doğru sınıf adını geçir
Derleme sonrası dependency eksik Çalışma zamanı Runtime dependency raporu ve dağıtım klasörü Bağımlılığı runtime kapsamına taşı
Scope/configuration uyuşmazlığı Derleme ile çalışma zamanı arasındaki geçiş Maven scope’u veya Gradle configuration’ı Bağımlılığı uygulamanın çalıştığı bağlama uygun tanımla
Gerekli JAR paket içine girmemiş Paketleme ve dağıtım Dağıtım klasörü ile paketleme çıktısı JAR’ı pakete ekle veya classpath’e dâhil et
Sınıf bulunduğu hâlde başlatılamıyor Sınıf başlatma Caused by zinciri ve başlatma sırasında gereken sınıflar İlk kök nedeni ve eksik/başarısız bağımlılığı düzelt

Üç somut kanıtı birlikte kontrol edin

  1. JAR içeriği: Beklenen sınıfın yolu, package adındaki noktalar eğik çizgiye çevrilmiş biçimde bulunmalıdır. Örneğin com.example.tools.Reporter için aranacak yol com/example/tools/Reporter.class olur. Sınıf farklı bir package altında veya farklı bir adla yer alıyorsa, Java kodundaki binary ad ile JAR içeriği uyuşmuyor demektir.
  2. Dağıtım klasörü: Uygulamanın ihtiyaç duyduğu dependency JAR’ı, yalnızca yerel Maven veya Gradle önbelleğinde değil, uygulamanın çalıştırıldığı paketleme ya da dağıtım klasöründe de bulunmalıdır. Derleme makinesinde bulunan dosya, hedef ortamın otomatik olarak göreceği anlamına gelmez.
  3. Gerçek başlatma komutu: Uygulamayı başlatan script, görev tanımı veya container ayarı incelenmeli; kullanılan -cp, -classpath ya da eşdeğer classpath değerinin hangi JAR’ları içerdiği görülmelidir. IDE içindeki çalıştırma ayarı ile üretimdeki başlatma komutu aynı olmayabilir.

Paketleme yöntemine, modüler yapıya ve kullanılan Java sürümüne bağlı ayrıntılar değişebileceği için, JAR’ın nasıl oluşturulduğu ile runtime classpath’in nasıl kurulduğunu proje ayarlarından doğrula. Burada güvenilir kanıt, yalnızca build dosyası değil, hedef ortamda oluşan gerçek dosya listesi ve uygulamayı başlatan gerçek komuttur.

İki mini senaryo ile farkı uygulamalı teşhis edin

Senaryo 1: Dinamik yüklemede yanlış binary sınıf adı

Uygulama, raporlayıcı sınıfını dinamik olarak yüklemek istiyor; ancak com.example.tools.Reporter yerine yalnızca Reporter veya package adı yanlış yazılmış bir değer gönderiyor.

Hata: ClassNotFoundException: Reporter.

Oluştuğu aşama: Kodun string üzerinden sınıf yüklemeyi denediği çalışma zamanı anı. Class.forName ve sınıf yükleyici yöntemleri, verilen adla eşleşen tanımı bulamazsa bu istisna türüyle karşılaşılabilir.

Kontrol edilecek kanıt: Hata mesajındaki tam ad, kaynak dosyanın başındaki package com.example.tools; bildirimi ve JAR içindeki com/example/tools/Reporter.class yolu karşılaştırılır.

Düzeltme: Doğru binary sınıf adı olan com.example.tools.Reporter kullanılır. Bu dosya JAR’da mevcut değilse sınıfın derleme çıktısına ve uygulamanın runtime classpath’ine gerçekten eklenmesi gerekir.

Senaryo 2: Derleme başarılı, çalışma paketinde dependency yok

Uygulama derlenir; fakat dağıtım klasörüne yalnızca uygulamanın kendi JAR’ı kopyalanır. Kod, çalışma sırasında dış kütüphanedeki bir sınıfa ihtiyaç duyduğunda bu JAR bulunamaz. Benzer belirti, ana sınıf bulunsa bile onun başlatılması sırasında ihtiyaç duyduğu başka bir sınıfın yüklenememesiyle de oluşabilir.

Hata: NoClassDefFoundError; çoğu zaman altında eksik sınıfı veya ilk yükleme sorununu açıklayan bir Caused by zinciri görülür.

Oluştuğu aşama: Derleme tamamlandıktan sonra sınıfın doğrulanması, çözülmesi veya başlatılması sırasında. JVM’nin sınıf yükleme sürecinde bir sınıf yükleyici ClassNotFoundException ile karşılaşırsa bunun çalışma akışında NoClassDefFoundError olarak görünmesi mümkündür.

Kontrol edilecek kanıt: Önce Caused by zincirindeki en alt sınıf adı belirlenir. Ardından Maven için mvn dependency:tree veya Gradle için seçili configuration’ı gösteren dependencies raporu incelenir; son olarak dependency JAR’ının dağıtım klasöründe ve gerçek -cp değerinde bulunup bulunmadığı kontrol edilir.

Düzeltme: Eksik JAR’ın uygun runtime scope/configuration içinde tanımlanması, paketleme çıktısına eklenmesi veya uygulamayı başlatan classpath’e açıkça dâhil edilmesi sağlanır. Tek başına yeniden derlemek, çalışma paketindeki eksik dosyayı düzeltmez.

Son kontrol: Hangi hatada hangi sırayı izlemelisiniz?

Teşhise rastgele dependency ekleyerek veya IDE’yi yeniden başlatarak değil, kanıtları sırayla inceleyerek başlayın. Önce hata türünü ve tam sınıf adını kaydedin. Ardından stack trace’in ilk bölümünü, özellikle de ilk hata satırını, Caused by ile başlayan asıl nedeni ve sınıfın hangi aşamada kullanıldığını birbirinden ayırın.

  • Package ve class adının yazımını, büyük-küçük harf duyarlılığını kontrol edin.
  • Derlenen çıktı içinde beklenen sınıf dosyasının gerçekten üretildiğini veya dependency içinde bulunduğunu doğrulayın.
  • Maven dependency raporunu ya da Gradle’ın ilgili çalışma zamanı classpath’ini inceleyin.
  • Oluşturulan JAR veya dağıtım paketinde gerekli dependency JAR’larının yer aldığını kontrol edin.
  • Uygulamanın gerçekten hangi classpath ile başlatıldığını görün; derleme classpath’i ile başlatma classpath’inin aynı olduğunu varsaymayın.
  • Sorunu aynı koşullarda yeniden üretin ve yalnızca gözlenen kanıtı açıklayan düzeltmeyi uygulayın.

Java’da package yapısını, dependency ilişkilerini ve stack trace okumayı yapılandırılmış biçimde geliştirmek istiyorsan Java birebir özel ders programı bu konularla doğrudan ilişkilendirilebilecek bir çalışma seçeneğidir.

Hata Oluştuğu aşama Kontrol edilecek kanıt Uygulanacak düzeltme
ClassNotFoundException Çalışma zamanında, genellikle sınıf adı dinamik olarak yüklenirken Tam sınıf adı, package yolu, ilgili runtime classpath ve dependency scope Yanlış adı düzeltmek, eksik dependency’yi doğru çalışma zamanı kapsamına almak veya gerçek başlatma classpath’ini düzeltmek
NoClassDefFoundError Sınıfın kullanılması, bağlanması veya başlatılması sırasında Eksik sınıfın adı, Caused by bölümü, paketleme çıktısı ve sınıf başlatma zinciri Eksik runtime dependency’yi, hatalı paketlemeyi veya başarısız sınıf başlatma nedenini düzeltmek

Bu akış, “JAR’ın içinde var mı?” sorusunu tek başına yeterli kabul etmez. Sınıfın derlenmiş olması, dependency raporunda görünmesi ve gerçek başlatma classpath’inde bulunması ayrı kanıtlardır. IDE’yi yeniden başlatmak bu kanıtları değiştirmediği için güvenilir bir teşhis yöntemi değildir; rastgele dependency eklemek de hangi classpath veya kapsam sorununun yaşandığını gizleyebilir.

Sık Sorulan Sorular

ClassNotFoundException ile NoClassDefFoundError arasındaki en kısa ve pratik fark nedir?

ClassNotFoundException çoğunlukla çalışma zamanında belirli bir sınıf adı yüklenmek istendiğinde sınıf bulunamadığında görülür. NoClassDefFoundError ise kodun ihtiyaç duyduğu sınıf, bağlantı veya başlatma aşamasında kullanılamadığında ortaya çıkar. Ayırıcı ipucu için hata adının yanında tam sınıf adını ve Caused by bölümünü birlikte okuyun.

Bir sınıf JAR dosyasının içinde olduğu hâlde neden NoClassDefFoundError alınabilir?

JAR’ın içinde bulunması, uygulamanın o JAR’ı gerçek çalışma zamanı classpath’inde gördüğünü kanıtlamaz. Ayrıca sınıfın bağımlı olduğu başka bir sınıf eksik olabilir veya sınıf başlatılırken bir hata oluşabilir. Bu nedenle JAR içeriğini, paketleme çıktısını, başlatma classpath’ini ve stack trace’in neden bölümünü birlikte kontrol etmek gerekir.

Dependency derleme sırasında bulunuyor, fakat uygulama çalışırken neden bulunamıyor?

Derleme classpath’i ile çalışma zamanı classpath’i farklı olabilir. Dependency yalnızca derleme kapsamına alınmış, dağıtım paketine eklenmemiş, yanlış runtime configuration içinde tanımlanmış veya uygulama farklı bir paket üzerinden başlatılmış olabilir. Dependency raporu tek başına yeterli değildir; gerçek başlatma komutu ve paketleme çıktısı da incelenmelidir.

Stack trace içindeki ilk hata ile “Caused by” satırı nasıl birlikte okunmalıdır?

İlk hata, uygulamanın hangi işlem sırasında başarısız olduğunu gösterir. Caused by bölümü ise bu başarısızlığın altındaki daha somut nedeni açıklar. Örneğin üstte NoClassDefFoundError bulunurken altta başka bir eksik sınıf veya sınıf başlatma hatası yer alabilir. Teşhiste yalnızca ilk satıra değil, zincirin en altındaki açıklayıcı nedene de bakın.

Bu sırayı izlemek, benzer görünen iki hatayı classpath, dependency kapsamı, paketleme ve sınıf başlatma kanıtları üzerinden ayırmayı kolaylaştırır.

Bu içerik aradığın cevabı verdi mi?
Yanıtın, hangi yazıları geliştirmemiz gerektiğini anlamamıza yardımcı olur.
Bu içeriğin üretilmesinde yapay zeka araçlarından destek alınmıştır.

Bu konudan sonra ne okuyabilirsin?

Tüm yazılar

İlgili Eğitimler

Berk Keskin, yazılım geliştirici ve eğitmen
Yazar

Berk Keskin Kimdir?

Yazılıma 12 yaşında başladı; İzmir Ekonomi Üniversitesi'ni bölüm birincisi ve yüksek şeref öğrencisi olarak tamamladı. Bugün yalnızca eğitim vermekle kalmıyor, sektörde aktif olarak yazılım projeleri geliştiriyor ve gerçek dünya deneyimini birebir derslerine taşıyor. Ezberden uzak, mühendislik zihniyetini merkeze alan sürdürülebilir öğrenme sistemleri tasarlayarak sorgulayan, üreten ve problem çözebilen yeni nesil yazılımcılar yetiştiriyor.

Sektörel Deneyim & Projeler

  • Ticarify Entegrasyon Yazılım logosu CEO Ticarify Entegrasyon YazılımPazaryerleri ve e-ticaret sitelerine otomatik e-fatura kesimi, sipariş ve kargo takibi hizmetleri sunan e-Dönüşüm platformunun API mimarisini ve yazılım ekibini yönetmektedir.
  • Benim Düğünüm logosu CEO Benim DüğünümDijital etkinlik ve anı paylaşım platformu.
  • Siberdizayn logosu Yazılım Ekibi Lideri SiberdizaynYüksek anlık oyuncu trafiğine sahip oyun kontrol panelleri ve sunucu altyapıları geliştiren yazılım ekibine liderlik etmektedir.
  • MEDYOGRAFYA 360° Dijital Çözümler logosu Dijital Strateji Lideri MEDYOGRAFYA 360° Dijital ÇözümlerŞirketlerin dijital çözümlerde uzun vadede nasıl ilerlemesi gerektiği ve dijital dönüşüm süreçlerinin yönetilmesine destek olmaktadır.
  • İzmir Ekonomi Üniversitesi logosu Danışma Kurulu Üyesi İzmir Ekonomi ÜniversitesiMezun olduğu üniversitesinde, Bilgisayar Programcılığı bölümünün akademik müfredatını güncel sektör ihtiyaçlarına göre şekillendirmek adına Danışma Kurulu'nda görev almaktadır.
WhatsApp Hemen Ara