NoClassDefFoundError
Java uygulamamı çalıştırdığımda bir an alıyorum . Bunun nedeni genellikle nedir?
NoClassDefFoundError
Java uygulamamı çalıştırdığımda bir an alıyorum . Bunun nedeni genellikle nedir?
Yanıtlar:
Bu, kodunuzun bağlı olduğu bir sınıf dosyası olduğunda ve derleme zamanında mevcut ancak çalışma zamanında bulunmadığında ortaya çıkar. Derleme süreniz ve çalışma zamanı sınıfyollarınızdaki farklılıkları arayın.
Bunun derleme zamanı ve çalışma zamanı arasındaki bir sınıf yolu uyuşmazlığından kaynaklanması mümkün olsa da, bu mutlaka doğru değildir.
Bu durumda iki veya üç farklı istisnayı doğrudan kafamızda tutmak önemlidir:
java.lang.ClassNotFoundException
Bu istisna, sınıfın sınıf yolunda bulunmadığını gösterir. Bu, sınıf tanımını yüklemeye çalıştığımızı ve sınıfın sınıfyolunda bulunmadığını gösterir.
java.lang.NoClassDefFoundError
Bu istisna, JVM'nin bir sınıfın tanımı için iç sınıf tanımı veri yapısına baktığını ve onu bulamadığını gösterir. Bu sınıf yolundan yüklenemediğini söylemekten farklıdır. Genellikle bu, daha önce sınıf yolundan bir sınıf yüklemeye çalıştığımızı gösterir, ancak bir nedenden dolayı başarısız oldu - şimdi sınıfı tekrar kullanmaya çalışıyoruz (ve bu yüzden son kez başarısız olduğu için yüklememiz gerekiyor), ancak ' yeniden yüklemeye bile çalışamayacağız, çünkü daha önce yükleyemedik (ve tekrar başarısız olacağımızdan şüpheleniyoruz). Önceki hata bir ClassNotFoundException veya bir ExceptionInInitializerError (statik başlatma bloğunda bir hata olduğunu gösteren) veya başka herhangi bir sorun olabilir. Mesele şu ki, NoClassDefFoundError mutlaka bir sınıfyolu problemi değildir.
Error: Could not find or load main class
hangi hata kategorisine sınıflandırılır?
İşte gösterilecek kod java.lang.NoClassDefFoundError
. Ayrıntılı açıklama için lütfen Jared'in cevabına bakınız .
NoClassDefFoundErrorDemo.java
public class NoClassDefFoundErrorDemo {
public static void main(String[] args) {
try {
// The following line would throw ExceptionInInitializerError
SimpleCalculator calculator1 = new SimpleCalculator();
} catch (Throwable t) {
System.out.println(t);
}
// The following line would cause NoClassDefFoundError
SimpleCalculator calculator2 = new SimpleCalculator();
}
}
SimpleCalculator.java
public class SimpleCalculator {
static int undefined = 1 / 0;
}
SimpleCalculator
sıfıra depoladı ? Birisi bu davranış için resmi belgelere bir başvuru var mı?
new SimpleCalculator()
çağrıldığında, ArithmeticException kaynaklı bir ExceptionInInitializerError alırsınız. İkinci aradığınızda new SimpleCalculator()
, NoClassDefFoundError'u diğer kadar saf alırsınız. Mesele şu ki, SimpleCalculator.class dışında çalışma zamanında sınıfyolunda olmama dışında bir sebeple NoClassDefFoundError alabilirsiniz.
Java'da NoClassDefFoundError
Tanım:
Java Virtual Machine, derleme zamanında mevcut olan belirli bir sınıfı bulamaz.
Derleme zamanı sırasında bir sınıf varsa, ancak çalışma zamanı sırasında java sınıfyolunda yoksa.
Örnekler:
NoClassDefFoundError'un basit bir örneği, sınıfın eksik bir JAR dosyasına ait olması veya JAR'ın sınıfyoluna eklenmemiş olması veya bazen kavanozun adı benim durumumdaki gibi biri tarafından değiştirilmişti. java.lang.NoClassDefFoundError ile başarısız ve neyin yanlış olduğunu merak ediyorduk.
Sadece çalışacağını düşündüğünüz sınıfyoluyla açıkça -classpath seçeneği ile çalışmayı deneyin ve eğer çalışıyorsa birisinin java sınıfyolunu geçersiz kıldığına dair kısa bir işarettir.
Olası çözümler:
Kaynaklar:
Bazen kod çalışma zamanında bulunan sınıfın uyumsuz bir sürümü ile derlendiğinde NoClassDefFound hata aldım bulduk. Hatırladığım özel örnek, apache eksen kütüphanesi ile. Aslında çalışma zamanı sınıfyolumda 2 sürüm vardı ve eski ve uyumsuz sürümü alıyordum ve doğru değil, NoClassDefFound hatasına neden oluyordu. Bu, buna benzer bir komut kullandığım bir komut satırı uygulamasındaydı.
set classpath=%classpath%;axis.jar
Kullanarak uygun sürümü almak için başardı:
set classpath=axis.jar;%classpath%;
Bu şimdiye kadar bulduğum en iyi çözüm .
org.mypackage
Sınıfları içeren bir paketimiz olduğunu varsayalım :
ve bu paketi tanımlayan dosyalar fiziksel olarak dizinin altında D:\myprogram
(Windows'ta) veya /home/user/myprogram
(Linux'ta) depolanır .
Dosya yapısı şöyle görünecektir:
Şimdi ise Java'nın çağırmak, biz çalıştırmak için uygulamanın adını belirtin: org.mypackage.HelloWorld
. Bununla birlikte, Java'ya paketimizi tanımlayan dosyaları ve dizinleri nerede arayacağını da söylemeliyiz. Programı başlatmak için aşağıdaki komutu kullanmalıyız:
Maven ile Spring Framework kullanıyordum ve projemdeki bu hatayı çözdüm .
Sınıfta bir çalışma zamanı hatası oluştu. Bir özelliği tamsayı olarak okuyordum, ancak özellik dosyasından değeri okurken değeri iki katına çıktı.
Bahar, çalışma zamanının hangi satırda başarısız olduğuna dair tam bir yığın izini vermedi. Basitçe söyledi NoClassDefFoundError
. Ama yerel bir Java uygulaması (MVC dışarı alarak) olarak yürüttüğümde ExceptionInInitializerError
, gerçek nedeni ve hatayı nasıl izlediğini verdi.
@ xli'nin cevabı bana kodumda neyin yanlış olabileceğine dair bir fikir verdi.
NoClassDefFoundError
aslında neden ExceptionInInitalizerError
oldu, neden oldu DateTimeParseException
). Biraz yanıltıcı, değil mi? Muhtemelen böyle yapmak için nedenleri olduğunu biliyorum, ama en azından küçük bir ipucuna sahip olmak çok güzel olurdu, bu NoClassDefFoundError
başka bir istisnanın sonucudur, çıkarmaya gerek kalmadan. ExceptionInInitializerError
Tekrar atmak çok daha net olurdu. Bazen ikisi arasındaki bağlantı o kadar açık olmayabilir.
Çalışma zamanı sınıf yükleyicisi tarafından yüklenen sınıflar, java kök yükleyicisi tarafından zaten yüklenen sınıflara erişemediğinde NoClassFoundError alıyorum. Farklı sınıf yükleyicileri farklı güvenlik etki alanlarında olduğundan (java'ya göre) jvm, kök yükleyici tarafından önceden yüklenmiş sınıfların çalışma zamanı yükleyici adres alanında çözümlenmesine izin vermez.
Programınızı 'java -javaagent: tracer.jar [YOUR java ARGS]' ile çalıştırın
Yüklenen sınıfı ve sınıfı yükleyen envanteri gösteren çıktı üretir. Bir sınıfın neden çözülemediğini izlemek çok yararlı.
// ClassLoaderTracer.java
// From: https://blogs.oracle.com/sundararajan/entry/tracing_class_loading_1_5
import java.lang.instrument.*;
import java.security.*;
// manifest.mf
// Premain-Class: ClassLoadTracer
// jar -cvfm tracer.jar manifest.mf ClassLoaderTracer.class
// java -javaagent:tracer.jar [...]
public class ClassLoadTracer
{
public static void premain(String agentArgs, Instrumentation inst)
{
final java.io.PrintStream out = System.out;
inst.addTransformer(new ClassFileTransformer() {
public byte[] transform(ClassLoader loader, String className, Class classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {
String pd = (null == protectionDomain) ? "null" : protectionDomain.getCodeSource().toString();
out.println(className + " loaded by " + loader + " at " + new java.util.Date() + " in " + pd);
// dump stack trace of the thread loading class
Thread.dumpStack();
// we just want the original .class bytes to be loaded!
// we are not instrumenting it...
return null;
}
});
}
}
Çok şey görebileceğiniz ilginç bir durum NoClassDefFoundErrors
şu durumlarda:
throw
Bir RuntimeException
de static
senin sınıfın bloğuExample
Example
static class Example {
static {
thisThrowsRuntimeException();
}
}
static class OuterClazz {
OuterClazz() {
try {
new Example();
} catch (Throwable ignored) { //simulating catching RuntimeException from static block
// DO NOT DO THIS IN PRODUCTION CODE, THIS IS JUST AN EXAMPLE in StackOverflow
}
new Example(); //this throws NoClassDefFoundError
}
}
NoClassDefError
ExceptionInInitializerError
statik bloktan atılır RuntimeException
.
Gördüğünüz bu özellikle önemlidir durum NoClassDefFoundErrors
sizin de birim testleri .
Bir şekilde, static
blok yürütmesini testler arasında "paylaşırsınız" , ancak ExceptionInInitializerError
birincisi sadece bir test durumunda olacaktır. Sorunlu Example
sınıfı kullanan ilk kişi . Example
Sınıfı kullanan diğer test senaryoları atılacaktır NoClassDefFoundErrors
.
Aşağıdaki teknik bana birçok kez yardımcı oldu:
System.out.println(TheNoDefFoundClass.class.getProtectionDomain().getCodeSource().getLocation());
burada TheNoDefFoundClass, programınız tarafından kullanılan aynı kütüphanenin daha eski bir sürümünü tercih etmesi nedeniyle "kaybolabilecek" sınıftır. Bu en sık, istemci yazılımı baskın bir konteynere konuşlandırıldığında, kendi sınıf yükleyicileri ve en popüler kütüphanelerin tonlarca eski versiyonuyla donatılmış durumlarla olur.
Kod oluşturduysanız (EMF, vb.) Tüm yığın alanını tüketen çok fazla statik başlatıcı olabilir.
Yığın Taşması sorusuna bakın Java yığın boyutu nasıl artırılır? .
NoClassDefFoundError
Bir zaman da ortaya çıkabilir statik denemeden başlatıcı etkilenen sınıf çalışır den yüklemek için bir özellikler dosyası örneğin çalışma zamanında mevcut olmayan bir kaynak paketi yüklemek için META-INF
dizine, ama yok. Yakalamazsanız NoClassDefFoundError
, bazen tam yığın izini göremezsiniz; bunun üstesinden gelmek için geçici olarak bir catch
cümle kullanabilirsiniz Throwable
:
try {
// Statement(s) that cause the affected class to be loaded
} catch (Throwable t) {
Logger.getLogger("<logger-name>").info("Loading my class went wrong", t);
}
for example a properties file that the affected class tries to load from the META-INF directory
. Bu aslında başıma geldi NoClassDefFoundError
ve eksik özellikler dosyasını ekleyerek çözmeyi başardım . Bu cevabı tam olarak ekledim çünkü biri bu hatayı belirtilen koşullar altında beklemiyordu.
static
bir kontrolsüz istisna tetiklenir ve sınıf init neden başlatma ... kaybetmek. Statik başlatmadan yayılan kontrol edilmeyen istisnalar bunu yapar.
static
başlatma nedeniyle değil ), davranışı gösteren gerçek bir örnek (yani bir MCVE) görmek ilgimi çekecektir.
Başka bir modülün Maven bağımlılığını projeme eklediğimde bu hatayı aldım, sorun nihayet -Xss2m
programımın JVM seçeneğine eklenerek çözüldü (JDK5.0'dan beri varsayılan olarak bir megabayt). Programın sınıfı yüklemek için yeterli yığını olmadığına inanılıyor.
Birisi java.lang.NoClassDefFoundError: org/apache/log4j/Logger
hata nedeniyle buraya gelirse , benim durumumda log4j 2 kullandığım için üretildi (ancak onunla birlikte gelen tüm dosyaları eklemedim) ve bazı bağımlılık kütüphanesi log4j 1'i kullandı. Çözüm Log4j'i eklemekti. 1.x köprü: log4j-1.2-api-<version>.jar
log4j ile gelen kavanoz 2. log4j 2 geçişinde daha fazla bilgi .
Benim durumumda, sorun Eclipse'nin aynı projenin iki farklı kopyasını ayırt edememesiydi. Biri gövdede kilitli (SVN sürüm kontrolü) ve diğeri aynı anda bir dalda çalışıyor. Çalışma kopyasındaki bir değişikliği JUnit test örneği olarak denedim, bu da özel bir iç sınıfı kendi başına bir kamu sınıfı olarak çıkarmayı da içeriyordu ve çalışırken, projenin diğer kopyasını başkalarına bakmak için açtım kodun değişmesi gereken bir kısmı. Bir noktada, NoClassDefFoundError
özel iç sınıfın orada olmadığından şikayet etti; yığın izini çift tıklatmak beni yanlış proje kopyasında kaynak dosyaya getirdi.
Projenin ana kopyasını kapatmak ve test senaryosunu tekrar çalıştırmak sorunu ortadan kaldırdı.
Bu hata, denetlenmeyen Java sürümü gereksinimleri nedeniyle ortaya çıkabilir .
Benim durumumda, SDKMAN kullanarak Java 9'dan Java 8'e geçerek yüksek profilli açık kaynaklı bir proje oluştururken bu hatayı çözebildim! .
sdk list java
sdk install java 8u152-zulu
sdk use java 8u152-zulu
Sonra aşağıda açıklandığı gibi temiz bir kurulum yapın.
Maven'i oluşturma aracınız olarak kullanırken , test devre dışı bırakılarak temiz bir 'kurulum' derlemesi yapmak bazen yararlıdır ve genellikle memnuniyet vericidir .
mvn clean install -DskipTests
Artık her şey inşa edildi ve kuruldu, devam edip testleri çalıştırabilirsiniz.
mvn test
Projemin Java Build Path'daki "Order and Export" sekmesinde bir sınıf vermediğimde NoClassDefFound hataları aldım. Projenin derleme yoluna eklediğiniz bağımlılıkların "Sipariş ve Dışa Aktar" sekmesine bir onay işareti koyduğunuzdan emin olun. Bkz. Tutulma uyarısı: XXXXXXXXXXX.jar dışa aktarılmaz veya yayınlanmaz. Çalışma Zamanı SınıfıNotFoundExceptions oluşabilir .
Benim durumumda JDK sürümlerindeki uyumsuzluk nedeniyle bu hatayı alıyordum. Uygulamayı Intelij'den çalıştırmayı denediğimde işe yaramadı, ancak komut satırından çalıştırıldı. Bunun nedeni Intelij'in Java 11 JDK ile kurulumunu çalıştırmaya çalışmasıydı, ancak komut satırında Java 8 JDK ile çalışıyordu. Dosya> Proje Yapısı> Proje Ayarları> Proje SDK'sı altında bu ayarı değiştirdikten sonra benim için çalıştı.
Herkes burada bazı Java yapılandırma şeyleri, JVM sorunları vb. Hakkında konuşuyor, benim durumumda hata bu konularla hiç ilgili değildi ve çok önemsiz ve çözülmesi kolay bir nedenim vardı: Denetleyicimdeki uç noktada yanlış bir ek açıklama vardı Spring Boot uygulaması).
Liberty sunucusuyla çalışan JavaEE NoClassDefFoundError ile ilginç bir sorun vardı. IMS kaynak bağdaştırıcıları kullanıyordum ve server.xml dosyamda imsudbJXA.rar için kaynak bağdaştırıcısı vardı. İmsudbXA.rar için yeni bir bağdaştırıcı eklediğimde, örneğin DLIException, IMSConnectionSpec veya SQLInteractionSpec nesneleri için bu hatayı almaya başlardım. Neden olduğunu anlayamadım ama sadece imsudbXA.rar kullanarak işim için yeni server.xml oluşturarak çözdüm. Server.xml içinde birden çok kaynak bağdaştırıcısı kullanmak eminim, sadece içine bakmak için zamanım yoktu.
Java, çalışma zamanında A sınıfını bulamadı. A sınıfı, farklı bir çalışma alanından ArtClient maven projesindeydi. Bu yüzden ArtClient'i Eclipse projeme aktardım. Projelerimden ikisi ArtClient'i bağımlılık olarak kullanıyordu. Bunlar için kütüphane referansını proje referansı olarak değiştirdim (Derleme Yolu -> Derleme Yolunu Yapılandır).
Ve sorun ortadan kayboldu.
SRC kitaplığından iki dosyayı kaldırdıktan sonra bu mesajı aldım ve onları geri getirdiğimde bu hata mesajını görmeye devam ettim.
Benim çözümüm: Eclipse'i yeniden başlatın. O zamandan beri bu mesajı bir daha görmedim :-)
Emin bu maçları olun module:app
ve module:lib
:
android {
compileSdkVersion 23
buildToolsVersion '22.0.1'
packagingOptions {
}
defaultConfig {
minSdkVersion 17
targetSdkVersion 23
versionCode 11
versionName "2.1"
}
{s
ve iki }
). Tamir edebilir misin?