Otrzymuję komunikat o NoClassDefFoundError
uruchomieniu aplikacji Java. Co zazwyczaj jest tego przyczyną?
java
noclassdeffounderror
John Meagher
źródło
źródło
Odpowiedzi:
Jest to spowodowane, gdy istnieje plik klasy, od którego zależy Twój kod, i jest on obecny w czasie kompilacji, ale nie można go znaleźć w czasie wykonywania. Sprawdź różnice w czasie kompilacji i ścieżkach klas środowiska wykonawczego.
źródło
Chociaż możliwe jest, że jest to spowodowane niedopasowaniem ścieżki klasowej między czasem kompilacji a czasem wykonywania, niekoniecznie jest to prawda.
W tym przypadku ważne jest zachowanie dwóch lub trzech różnych wyjątków:
java.lang.ClassNotFoundException
Ten wyjątek wskazuje, że klasa nie została znaleziona w ścieżce klasy. Oznacza to, że próbowaliśmy załadować definicję klasy, a klasa nie istniała w ścieżce klasy.java.lang.NoClassDefFoundError
Ten wyjątek wskazuje, że JVM szukał definicji swojej klasy w wewnętrznej strukturze danych definicji klasy i jej nie znalazł. Jest to inne niż stwierdzenie, że nie można go załadować ze ścieżki klas. Zwykle oznacza to, że poprzednio próbowaliśmy załadować klasę ze ścieżki klas, ale z jakiegoś powodu nie udało się - teraz próbujemy ponownie użyć tej klasy (i dlatego musimy ją załadować, ponieważ poprzednio nie powiodła się), ale „ nawet nie będziemy próbować go załadować, ponieważ nie udało nam się go wcześniej załadować (i mamy uzasadnione podejrzenia, że znowu się nie powiedziemy). Wcześniejszym niepowodzeniem może być ClassNotFoundException lub ExceptionInInitializerError (wskazujący błąd w bloku statycznej inicjalizacji) lub dowolną liczbę innych problemów. Chodzi o to, że NoClassDefFoundError niekoniecznie jest problemem ścieżki klasowej.źródło
Error: Could not find or load main class
, zostanie zaklasyfikowany do jakiej kategorii błędu?Oto kod do zilustrowania
java.lang.NoClassDefFoundError
. Zobacz odpowiedź Jareda do szczegółowego wyjaśnienia.NoClassDefFoundErrorDemo.java
SimpleCalculator.java
źródło
SimpleCalculator
po podzieleniu przez zero? Czy ktoś ma odniesienie do oficjalnej dokumentacji tego zachowania?new SimpleCalculator()
wywołaniu pojawia się wyjątek ExceptionInInitializerError spowodowany wyjątkiem ArithmeticException. Przy drugim wywołaniunew SimpleCalculator()
otrzymasz NoClassDefFoundError tak czysty jak każdy inny. Chodzi o to, że możesz uzyskać NoClassDefFoundError z innego powodu niż SimpleCalculator.class, który nie znajduje się w ścieżce klas w czasie wykonywania.NoClassDefFoundError W Javie
Definicja:
Java Virtual Machine nie jest w stanie znaleźć konkretnej klasy w czasie wykonywania, która była dostępna w czasie kompilacji.
Jeśli klasa była obecna w czasie kompilacji, ale nie była dostępna w ścieżce klas Java w czasie wykonywania.
Przykłady:
Prostym przykładem NoClassDefFoundError jest to, że klasa należy do brakującego pliku JAR lub JAR nie został dodany do ścieżki klasy lub czasami nazwa jar została zmieniona przez kogoś takiego jak w moim przypadku jeden z moich kolegów zmienił tibco.jar na tibco_v3.jar, a program jest błąd z java.lang.NoClassDefFoundError i zastanawiałem się, co jest nie tak.
Po prostu spróbuj uruchomić z jawnie opcją -classpath ze ścieżką klasy, która Twoim zdaniem będzie działać, a jeśli działa, to jest to pewnie krótki znak, że ktoś przesłonił ścieżkę klasy Java.
Możliwe rozwiązania:
Zasoby:
3 sposoby rozwiązania NoClassDefFoundError
java.lang.NoClassDefFoundError Wzorce problemów
źródło
Odkryłem, że czasami pojawia się błąd NoClassDefFound, gdy kod jest kompilowany z niekompatybilną wersją klasy znalezioną w czasie wykonywania. Konkretne wystąpienie, które pamiętam, dotyczy biblioteki osi apache. W mojej ścieżce klas środowiska wykonawczego były w rzeczywistości 2 wersje, które pobierały nieaktualną i niekompatybilną wersję, a nie poprawną, powodując błąd NoClassDefFound. To było w aplikacji wiersza poleceń, w której korzystałem z polecenia podobnego do tego.
Byłem w stanie uzyskać odpowiednią wersję, używając:
źródło
To najlepsze rozwiązanie jakie do tej pory znalazłem.
Załóżmy, że mamy pakiet o nazwie
org.mypackage
zawierający klasy:a pliki definiujące ten pakiet są przechowywane fizycznie w katalogu
D:\myprogram
(w systemie Windows) lub/home/user/myprogram
(w systemie Linux).Struktura pliku będzie wyglądać następująco:
Kiedy wzywamy Java, możemy określić nazwę aplikacji do uruchomienia:
org.mypackage.HelloWorld
. Musimy jednak powiedzieć Javie, gdzie szukać plików i katalogów definiujących nasz pakiet. Aby uruchomić program, musimy użyć następującego polecenia:źródło
Korzystałem z Spring Framework z Maven i rozwiązałem ten błąd w moim projekcie.
W klasie wystąpił błąd czasu wykonywania. Czytałem właściwość jako liczbę całkowitą, ale kiedy odczytała wartość z pliku właściwości, jej wartość była podwójna.
Wiosna nie dała mi pełnego śladu stosu, w której linii wystąpił błąd środowiska wykonawczego. Po prostu powiedział
NoClassDefFoundError
. Ale kiedy wykonałem go jako natywną aplikację Java (biorąc go z MVC), dałemExceptionInInitializerError
która była prawdziwa przyczyna i w jaki sposób wyśledziłem błąd.Odpowiedź @ xli dała mi wgląd w to, co może być źle w moim kodzie.
źródło
NoClassDefFoundError
tak naprawdę było spowodowane przezExceptionInInitalizerError
, co było spowodowane przezDateTimeParseException
). To trochę mylące, prawda? Wiem, że prawdopodobnie mieli ku temu powody, ale tak miło byłoby mieć chociaż małą podpowiedź, któraNoClassDefFoundError
była wynikiem innego wyjątku, bez potrzeby wnioskowania.ExceptionInInitializerError
Ponowne rzucenie byłoby znacznie wyraźniejsze. Czasami związek między nimi może nie być tak oczywisty.Dostaję NoClassFoundError, gdy klasy ładowane przez moduł ładujący środowiska wykonawczego nie mogą uzyskać dostępu do klas już załadowanych przez program ładujący root Java. Ponieważ różne moduły ładujące znajdują się w różnych domenach bezpieczeństwa (zgodnie z Javą), Jvm nie pozwoli na rozpoznanie klas już załadowanych przez program ładujący root w przestrzeni adresowej modułu ładującego środowisko wykonawcze.
Uruchom swój program z „java -javaagent: tracer.jar [YOUR java ARGS]”
Generuje dane wyjściowe pokazujące załadowaną klasę i środowisko env loadera, które załadowało klasę. Bardzo pomocne jest śledzenie, dlaczego nie można rozwiązać klasy.
źródło
Ciekawym przypadkiem, w którym możesz wiele zobaczyć,
NoClassDefFoundErrors
jest:throw
RuntimeException
wstatic
bloku klasyExample
Example
NoClassDefError
zostanie wyrzucony w towarzystwie zExceptionInInitializerError
bloku statycznegoRuntimeException
.Jest to szczególnie ważny przypadek, gdy widzisz
NoClassDefFoundErrors
w TESTACH JEDNOSTKI .W pewien sposób „udostępniasz”
static
wykonanie bloku między testami, ale początkowaExceptionInInitializerError
będzie tylko w jednym przypadku testowym. Pierwszy, który korzysta z problematycznejExample
klasy. Inne przypadki testowe korzystające z tejExample
klasy po prostu rzucąNoClassDefFoundErrors
.źródło
Poniższa technika pomogła mi wiele razy:
gdzie TheNoDefFoundClass to klasa, która może zostać „utracona” z powodu preferencji dla starszej wersji tej samej biblioteki używanej przez twój program. Zdarza się to najczęściej w przypadkach, gdy oprogramowanie klienckie jest wdrażane w dominującym kontenerze, uzbrojonym we własne moduły ładujące klasy i mnóstwo starożytnych wersji najpopularniejszych bibliotek.
źródło
W przypadku wygenerowania kodu (EMF itp.) Może być zbyt wiele statycznych inicjatorów, które zajmują całe miejsce na stosie.
Zobacz pytanie Przepełnienie stosu Jak zwiększyć rozmiar stosu Java? .
źródło
Rozwiązałem problem, wyłączając preDexLibraries dla wszystkich modułów:
źródło
NoClassDefFoundError
może również wystąpić, gdy inicjator statyczny próbuje załadować pakiet zasobów, który nie jest dostępny w środowisku wykonawczym, na przykład plik właściwości, który klasa, której dotyczy problem, próbuje załadować zMETA-INF
katalogu, ale go nie ma. Jeśli nie złapieszNoClassDefFoundError
, czasami nie będziesz w stanie zobaczyć pełnego śladu stosu; Aby temu zaradzić, możesz tymczasowo użyćcatch
klauzuli, abyThrowable
:źródło
for example a properties file that the affected class tries to load from the META-INF directory
. Tak się właściwie stało i udało mi się rozwiązaćNoClassDefFoundError
, dodając brakujący plik właściwości. Dodałem tę odpowiedź właśnie dlatego, że nie można oczekiwać tego błędu w wyżej wymienionych okolicznościach.static
inicjalizacji ... co spowodowało niesprawdzony wyjątek i spowodowało inicjację nie zdać. Zrobiłby to każdy niesprawdzony wyjątek propagowany z inicjalizacji statycznej.static
inicjalizacji), chciałbym zobaczyć rzeczywisty przykład (np. MCVE), który demonstruje zachowanie.Wystąpił ten błąd, gdy dodałem zależność Maven od innego modułu do mojego projektu, problem został w końcu rozwiązany przez dodanie
-Xss2m
do opcji JVM mojego programu (domyślnie jest to jeden megabajt od JDK5.0). Uważa się, że program nie ma wystarczającego stosu, aby załadować klasę.źródło
Jeśli ktoś tu przychodzi z powodu
java.lang.NoClassDefFoundError: org/apache/log4j/Logger
błędu, w moim przypadku został on utworzony, ponieważ użyłem log4j 2 (ale nie dodałem wszystkich plików, które są z nim związane), a niektóre biblioteki zależności wykorzystały log4j 1. Rozwiązaniem było dodanie Log4j Most 1.x: słoiklog4j-1.2-api-<version>.jar
dostarczany z log4j 2. Więcej informacji na temat migracji log4j 2 .źródło
Dwie różne kopie kasy tego samego projektu
W moim przypadku problemem była niezdolność Eclipse do rozróżnienia dwóch różnych kopii tego samego projektu. Mam jeden zablokowany na pniu (kontrola wersji SVN), a drugi pracuje w jednej gałęzi na raz. Wypróbowałem jedną zmianę w kopii roboczej jako przypadek testowy JUnit, która obejmowała wyodrębnienie prywatnej klasy wewnętrznej, aby sama była klasą publiczną i podczas gdy działała, otwieram drugą kopię projektu, aby rozejrzeć się po innej część kodu, która wymagała zmian. W pewnym momencie
NoClassDefFoundError
wyskoczyli narzekając, że nie ma prywatnej klasy wewnętrznej; dwukrotne kliknięcie śledzenia stosu doprowadziło mnie do pliku źródłowego w niewłaściwej kopii projektu.Zamknięcie kopii projektu i ponowne uruchomienie skrzynki testowej pozbyło się problemu.
źródło
Ten błąd może być spowodowany niesprawdzonymi wymaganiami dotyczącymi wersji Java .
W moim przypadku udało mi się rozwiązać ten błąd, budując głośny projekt open source, przechodząc z Java 9 na Java 8 za pomocą SDKMAN! .
Następnie wykonaj czystą instalację, jak opisano poniżej.
Kiedy używasz Maven jako narzędzia do kompilacji, czasem pomocne jest - i zwykle satysfakcjonujące - wykonanie czystej kompilacji „instaluj” z wyłączonym testowaniem .
Teraz, gdy wszystko zostało zbudowane i zainstalowane, możesz przejść testy i przeprowadzić je.
źródło
Wystąpiły błędy NoClassDefFound, gdy nie wyeksportowałem klasy na karcie „Zamów i eksportuj” na ścieżce kompilacji Java mojego projektu. Pamiętaj, aby zaznaczyć znacznik wyboru na karcie „Zamów i eksportuj” wszystkich zależności dodanych do ścieżki kompilacji projektu. Zobacz ostrzeżenie Eclipse: XXXXXXXXXXX.jar nie zostanie wyeksportowany ani opublikowany. Może to spowodować wyjątki Runtime ClassNotFoundExceptions .
źródło
Może to być również spowodowane tym, że skopiujesz plik kodu z IDE z określoną nazwą pakietu i chcesz spróbować uruchomić go za pomocą terminala. Najpierw musisz usunąć nazwę pakietu z kodu. To mi się przydarza.
źródło
W moim przypadku występował ten błąd z powodu niedopasowania w wersjach JDK. Kiedy próbowałem uruchomić aplikację z Intelij, to nie działało, ale działało z wiersza poleceń. Wynika to z faktu, że Intelij próbował uruchomić go z zainstalowanym pakietem JDK Java 11, ale w wierszu komend uruchomiono go z pakietem JDK Java 8. Po zmianie tego ustawienia w Plik> Struktura projektu> Ustawienia projektu> Zestaw SDK projektu, zadziałało to dla mnie.
źródło
Wszyscy mówią tutaj o niektórych kwestiach związanych z konfiguracją Java, problemami z JVM itp. W moim przypadku błąd nie był w ogóle związany z tymi tematami i miał bardzo trywialny i łatwy do rozwiązania powód: miałem niepoprawną adnotację w punkcie końcowym w moim kontrolerze ( Aplikacja Spring Boot).
źródło
Miałem interesujący problem z NoClassDefFoundError w JavaEE współpracującym z serwerem Liberty. Korzystałem z adapterów zasobów IMS, a mój plik server.xml miał już adapter zasobów dla imsudbJXA.rar. Kiedy dodałem nowy adapter do imsudbXA.rar, zacząłem otrzymywać ten błąd na przykład dla obiektów DLIException, IMSConnectionSpec lub SQLInteractionSpec. Nie mogłem zrozumieć, dlaczego, ale rozwiązałem ten problem, tworząc nowy server.xml do mojej pracy, używając tylko imsudbXA.rar. Jestem pewien, że używanie wielu adapterów zasobów w pliku server.xml jest w porządku, po prostu nie miałem czasu, aby się tym zająć.
źródło
Java nie mogła znaleźć klasy A w środowisku wykonawczym. Klasa A była w projekcie maven ArtClient z innego obszaru roboczego. Zaimportowałem więc ArtClient do mojego projektu Eclipse. Dwa moje projekty wykorzystywały ArtClient jako zależność. Zmieniłem odwołanie do biblioteki na odwołanie do projektu dla tych (Ścieżka kompilacji -> Konfiguruj ścieżkę kompilacji).
Problem zniknął.
źródło
Miałem ten sam problem i miałem zapas na wiele godzin.
Znalazłem rozwiązanie. W moim przypadku zdefiniowano z tego powodu metodę statyczną. JVM nie może utworzyć kolejnego obiektu tej klasy.
Na przykład,
źródło
Otrzymałem ten komunikat po usunięciu dwóch plików z biblioteki SRC, a kiedy je przywróciłem, nadal widziałem ten komunikat o błędzie.
Moje rozwiązanie brzmiało: Uruchom ponownie Eclipse. Od tego czasu nie widziałem tego komunikatu ponownie :-)
źródło
Upewnij się, że mecze w
module:app
imodule:lib
:źródło
{s
i dwa}
). Czy możesz to naprawić?