Przyczyny otrzymania java.lang.VerifyError

191

Badam następujące kwestie java.lang.VerifyError

java.lang.VerifyError: (class: be/post/ehr/wfm/application/serviceorganization/report/DisplayReportServlet, method: getMonthData signature: (IILjava/util/Collection;Ljava/util/Collection;Ljava/util/HashMap;Ljava/util/Collection;Ljava/util/Locale;Lorg/apache/struts/util/MessageRe˜̴Mt̴MÚw€mçw€mp:”MŒŒ
                at java.lang.Class.getDeclaredConstructors0(Native Method)
                at java.lang.Class.privateGetDeclaredConstructors(Class.java:2357)
                at java.lang.Class.getConstructor0(Class.java:2671)

Występuje po uruchomieniu serwera jboss, na którym wdrożony jest serwlet. Jest skompilowany z jdk-1.5.0_11 i próbowałem go ponownie skompilować z jdk-1.5.0_15 bez powodzenia. Oznacza to, że kompilacja działa poprawnie, ale po wdrożeniu występuje błąd java.lang.VerifyError.

Kiedy zmieniłem nazwę metody i otrzymałem następujący błąd:

java.lang.VerifyError: (class: be/post/ehr/wfm/application/serviceorganization/report/DisplayReportServlet, method: getMD signature: (IILjava/util/Collection;Lj    ava/util/Collection;Ljava/util/HashMap;Ljava/util/Collection;Ljava/util/Locale;Lorg/apache/struts/util/MessageResources ØÅN|ØÅNÚw€mçw€mX#ÖM|XÔM
            at java.lang.Class.getDeclaredConstructors0(Native Method)
            at java.lang.Class.privateGetDeclaredConstructors(Class.java:2357
            at java.lang.Class.getConstructor0(Class.java:2671)
            at java.lang.Class.newInstance0(Class.java:321)
            at java.lang.Class.newInstance(Class.java:303)

Widać, że wyświetlana jest większa część sygnatury metody.

Rzeczywisty podpis metody to

  private PgasePdfTable getMonthData(int month, int year, Collection dayTypes,
                          Collection calendarDays,
                          HashMap bcSpecialDays,
                          Collection activityPeriods,
                          Locale locale, MessageResources resources) throws   Exception {

Próbowałem już na to patrzeć javapi to daje metodzie podpis taki, jaki powinien być.

Kiedy moi inni koledzy sprawdzają kod, kompilują go i wdrażają, mają ten sam problem. Gdy serwer kompilacji pobiera kod i wdraża go w środowiskach programistycznych lub testowych (HPUX), występuje ten sam błąd. Również automatyczna maszyna testująca z systemem Ubuntu pokazuje ten sam błąd podczas uruchamiania serwera.

Reszta aplikacji działa poprawnie, tylko jeden serwlet nie działa. Przydałyby się pomysły, gdzie szukać.

Jeroen Wyseur
źródło
1
Mam to przy użyciu niewłaściwej wersji CompareFailure. ZAWSZE szukałem ... to było bolesne
Tim Boland
1
Mam go, gdy korzystam z natychmiastowego uruchamiania w Android Studio (hotswapping przy kompilacji). Wyłączenie to wystarczyło.
Serge

Odpowiedzi:

188

java.lang.VerifyError może być wynikiem kompilacji z inną biblioteką niż w środowisku wykonawczym.

Na przykład przydarzyło mi się to podczas próby uruchomienia programu skompilowanego z Xerces 1, ale Xerces 2 został znaleziony w ścieżce klas. Wymagane klasy (w org.apache.*przestrzeni nazw) zostały znalezione w czasie wykonywania, więc nieClassNotFoundException zostało to wynik. Wprowadzono zmiany w klasach i metodach, tak że podpisy metod znalezione w środowisku wykonawczym nie zgadzały się z tym, co było w czasie kompilacji.

Zwykle kompilator oznaczy problemy, w których sygnatury metod nie są zgodne. JVM ponownie zweryfikuje kod bajtowy, gdy klasa zostanie załadowana, i zgłasza, VerifyErrorgdy kod bajtowy próbuje zrobić coś, co nie powinno być dozwolone - np. Wywołuje metodę, która zwraca, Stringa następnie przechowuje tę zwracaną wartość w polu zawierającym List.

Kevin Panko
źródło
3
Jedną rzeczą do dodania, czasami jest to wina IDE lub urządzenie, którego kod bajtowy jest niewłaściwy. Spróbuj ponownie uruchomić IDE, aby rozpoznać problem z synchronizacją. W przeciwnym razie usuń i ponownie zainstaluj aplikację. Ponowne uruchomienie urządzenia może również pomóc.
ima747,
2
Aby dowiedzieć się, która klasa jest winowajcą, dodaj argument VM, -verbose:classa następnie poszukaj klasy tuż przed jej załadowaniem java.lang.VerifyError. Będzie to miało ścieżkę do pliku JAR. Użyj javapi porównaj to z klasą, z którą się kompilujesz. Uznałem to za przydatne, ponieważ klasa zgłoszona w błędzie nie była przyczyną, ponieważ był to jeden z argumentów.
steinybot
21

java.lang.VerifyError są najgorsze.

Ten błąd wystąpiłby, gdyby rozmiar kodu bajtowego metody przekraczał limit 64 kb; ale pewnie byście to zauważyli.

Czy jesteś w 100% pewien, że ta klasa nie jest obecna w ścieżce klas w innym miejscu twojej aplikacji, może w innym słoju?

Ponadto z twojego stacktrace jest kodowanie znaków w pliku źródłowym ( utf-8?) Czy to prawda?

p3t0r
źródło
Jestem pewien, że nie ma go gdzie indziej. To 43Kb, to wciąż duża klasa.
Jeroen Wyseur
Dzięki za ten post, w moim przypadku było to inne kodowanie: pliki XMl JasperReports zapisują kodowanie i wersję Java, musisz to ustawić odpowiednio do ustawień projektu (przez iReport). To był problem tutaj, dziękuję za pomysł z kodowaniem! :)
Tobias
To był mój problem z testami Androida, naprawiłem to przez multideksowanie.
Prakash Nadar
10

Jak powiedział Kevin Panko, dzieje się tak głównie ze względu na zmiany w bibliotece. Tak więc w niektórych przypadkach „czyste” projektu (katalogu), a następnie kompilacja załatwia sprawę.

Pływ
źródło
9

Jedną z rzeczy, które możesz wypróbować, jest -Xverify:allsprawdzenie kodu bajtowego przy ładowaniu, a czasem wyświetla pomocne komunikaty o błędach, jeśli kod bajtowy jest nieprawidłowy.

Alex Miller
źródło
8

VerifyError oznacza, że ​​plik klasy zawiera kod bajtowy, który jest poprawny składniowo, ale narusza pewne ograniczenia semantyczne, np. Cel skoku przekraczający granice metody.

Zasadniczo błąd VerifyError może wystąpić tylko wtedy, gdy wystąpi błąd kompilatora lub gdy plik klasy zostanie uszkodzony w inny sposób (np. Z powodu wadliwej pamięci RAM lub awarii HD).

Spróbuj skompilować z inną wersją JDK i na innym komputerze.

Michael Borgwardt
źródło
5

W moim przypadku mój projekt na Androida zależy od innego projektu Java skompilowanego dla Java 7. java.lang.VerifyErrorzniknął po zmianie poziomu zgodności kompilatora tego projektu Java na 6.0

Później dowiedziałem się, że jest to problem Dalvik: https://groups.google.com/forum/?fromgroups#!topic/android-developers/sKsMTZ42pwE

Michał Vician
źródło
1
Dalvik to tylko rozgałęziona wersja Java6, więc żadne funkcje Java7 nie są dostępne!
Jeroen Wyseur
4

Dostawałem ten problem z powodu manglowania pliku klasy przez pack200. Trochę poszukiwań podniosło ten błąd java . Zasadniczo ustawienie --effort=4spowodowało, że problem zniknął.

Używam java 1.5.0_17 (chociaż pojawił się w każdym wariancie java 1.5, w którym go wypróbowałem).

Mike Miller
źródło
3

Rozwiązałem podobny problem java.lang.VerifyError, zastępując go

        catch (MagickException e)

z

        catch (Exception e)

gdzie MagickException został zdefiniowany w projekcie bibliotecznym (od którego mój projekt jest zależny).

Po tym mam java.lang.NoClassDefFoundErrorokoło klasy z tej samej biblioteki (naprawione zgodnie z https://stackoverflow.com/a/9898820/755804 ).

18446744073709551615
źródło
1
To zadziałało dla mnie ... Naprawdę chciałbym dowiedzieć się, jaki był błąd oprócz „zastąp mnie wyjątkiem ogólnym i będę działać”.
Alex Hart
@AlexHart jest dla Androida, ale prawdopodobnie ta sama logika miałaby zastosowanie do korporacyjnej Java: stackoverflow.com/a/36814155/253468
TWiStErRob
2

Może się to zdarzyć na Androidzie, gdy próbujesz załadować bibliotekę skompilowaną z JDK Oracle.

Oto problem dla klienta HTTP Ning Async.

Martin Konicek
źródło
Czy już znalazłeś rozwiązanie tego problemu @MartinKonicek
Abimbola Esuruoso
2

W moim przypadku musiałem usunąć ten blok:

compileOptions {
    sourceCompatibility JavaVersion.VERSION_1_7
    targetCompatibility JavaVersion.VERSION_1_7
}

Pokazuje błąd w pobliżu Fragment.showDialog()wywołania metody.

ViliusK
źródło
2

Minimalny przykład generujący błąd

Jedną z prostych możliwości jest użycie Jasmin lub ręczna edycja kodu bajtowego za pomocą edytora plików binarnych.

Pozwala utworzyć voidmetodę bez returninstrukcji (wygenerowanej przez return;instrukcję w Javie), która według JVMS jest nielegalna.

W Jasmin możemy napisać:

.class public Main
.super java/lang/Object

.method public static main([Ljava/lang/String;)V
   aload_0 ; Just so that we won't get another verify error for empty code.
.end method

Następnie robimy javac Main.ji javap -v Mainmówimy, że skompilowaliśmy:

public static void main(java.lang.String[]);
  descriptor: ([Ljava/lang/String;)V
  flags: ACC_PUBLIC, ACC_STATIC
  Code:
    stack=1, locals=1, args_size=1
       0: aload_0

tak naprawdę nie ma instrukcji powrotu.

Teraz, gdy spróbujemy uruchomić java Main, otrzymamy:

Error: A JNI error has occurred, please check your installation and try again
Exception in thread "main" java.lang.VerifyError: (class: NoReturn, method: main signature: ([Ljava/lang/String;)V) Falling off the end of the code
        at java.lang.Class.getDeclaredMethods0(Native Method)
        at java.lang.Class.privateGetDeclaredMethods(Class.java:2701)
        at java.lang.Class.privateGetMethodRecursive(Class.java:3048)
        at java.lang.Class.getMethod0(Class.java:3018)
        at java.lang.Class.getMethod(Class.java:1784)
        at sun.launcher.LauncherHelper.validateMainClass(LauncherHelper.java:544)
        at sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:526)

Ten błąd nie może się zdarzyć w Javie normalnie, ponieważ kompilator Javy dodaje niejawna returndo voidmetod nas. Dlatego nie musimy dodawać a returndo naszych mainmetod. Możesz to sprawdzić za pomocąjavap .

JVMS

Błąd VerifyError występuje, gdy próbujesz uruchomić niektóre typy nielegalnych plików klas, jak określono w JVMS 7 rozdział 4.5

JVMS mówi, że gdy Java ładuje plik, musi uruchomić serię kontroli, aby sprawdzić, czy plik klasy jest w porządku przed uruchomieniem.

Takie błędy nie mogą zostać wygenerowane w jednym cyklu kompilacji i uruchomienia kodu Java, ponieważ JVMS 7 4.10 mówi :

Mimo że kompilator dla języka programowania Java może generować tylko pliki klas, które spełniają wszystkie ograniczenia statyczne i strukturalne [...]

Aby zobaczyć przykład minimalnej awarii, będziemy musieli wygenerować kod źródłowy bez javac.

Ciro Santilli
źródło
1

Ta strona może dać ci kilka wskazówek - http://www.zanthan.com/itymbi/archives/000337.html

W tej metodzie może być subtelny błąd, którego javac nie wykryje. Trudno zdiagnozować, chyba że opublikujesz tutaj całą metodę.

Możesz zacząć od zadeklarowania jak największej liczby zmiennych, jak to tylko możliwe ..., które wychwyciłyby błąd wymieniony na stronie zanthan i często jest dobrą praktyką.

Lars Westergren
źródło
1
Ten facet trafił na błąd kompilatora w 2002 roku, ale ten błąd został naprawiony od tego czasu.
Kevin Panko
1

Cóż, w moim przypadku mój projekt A był zależny od innego, powiedzmy X (A używał niektórych klas zdefiniowanych w X). Więc kiedy dodałem X jako projekt referencyjny na ścieżce kompilacji A, dostałem ten błąd. Jednak gdy usunąłem X jako projekt, do którego się odwołałem, i umieściłem słoik X jako jedną z bibliotek, problem został rozwiązany.

użytkownik2484130
źródło
1

Sprawdź, czy w ścieżce klasy znajduje się wiele wersji tego samego pliku jar.

Na przykład miałem ścieżkę opennlp-tools-1.3.0.jar i opennlp-tools-1.5.3.jar na mojej ścieżce klasy i otrzymałem ten błąd. Rozwiązaniem było usunięcie opennlp-tools-1.3.0.jar.

demongolem
źródło
1

Innym powodem tego błędu może być kombinacja AspectJ <= 1.6.11 z JRE> 6.

Zobacz Eclipse Bug 353467 i bilet Kieker 307 .

Jest to szczególnie prawdziwe, gdy wszystko działa poprawnie w JRE 6, a przejście do JRE7 psuje wszystko.

Alexander Wessel
źródło
1

Może się to również zdarzyć, gdy masz wiele importów modułów za pomocą maven. Będą dwie lub więcej klas o dokładnie takiej samej nazwie (ta sama nazwa kwalifikowana). Ten błąd wynika z różnicy interpretacji czasu kompilacji i czasu wykonywania.

Toumi
źródło
1

Jeśli przeprowadzasz migrację do java7 lub używasz java7, ogólnie można zauważyć ten błąd. Napotkałem powyższe błędy i bardzo się starałem, aby znaleźć podstawową przyczynę. Sugerowałbym, aby spróbować dodać argument JVM „-XX: -UseSplitVerifier” podczas uruchamiania aplikacji.

Ulhas N.
źródło
1

Po aktualizacji Gradlew Android Studio 3.6.1 doszło do awarii API 19 w kompilacji wydania.

Wystąpił błądGlide biblioteki . Rozwiązaniem jest przepisanie proguard-rules.txt .

Również obniżenie Gradledziała ( classpath 'com.android.tools.build:gradle:3.5.3'), ale jest to przestarzałe rozwiązanie, nie używaj go.

CoolMind
źródło
0

Chociaż powód wspomniany przez Kevina jest poprawny, ale zdecydowanie przejdę poniżej, zanim przejdę do czegoś innego:

  1. Sprawdź cglibsmoją ścieżkę klasy.
  2. Sprawdź hibernatewersje w mojej ścieżce klasy.

Są duże szanse, że posiadanie wielu lub sprzecznych wersji któregokolwiek z powyższych może powodować nieoczekiwane problemy, takie jak ten, o którym mowa.

Sandeep Jindal
źródło
0

java.lang.VerifyError oznacza, że ​​skompilowany kod bajtowy odnosi się do czegoś, czego Android nie może znaleźć. Ten błąd VerError wystawia mi tylko KitKat4.4 i mniejszą wersję, ale nie w powyższej wersji , nawet jeśli uruchomiłem tę samą kompilację na obu urządzeniach. kiedy użyłem parsera json json ze starszej wersji, pokazuje java.lang.verifyerror

compile 'com.fasterxml.jackson.core:jackson-databind:2.2.+'
compile 'com.fasterxml.jackson.core:jackson-core:2.2.+'
compile 'com.fasterxml.jackson.core:jackson-annotations:2.2.+'

Następnie zmieniłem Zależność na najnowszą wersję 2.2 na 2.7 bez biblioteki podstawowej , a następnie działa. co oznacza, że ​​Metody i inna zawartość rdzenia jest migrowana do najnowszej wersji Databind2.7 . To rozwiązuje moje problemy.

compile 'com.fasterxml.jackson.core:jackson-annotations:2.7.0-rc3'
compile 'com.fasterxml.jackson.core:jackson-databind:2.7.0-rc3'
anand krish
źródło
Skąd wiesz, którego JAR szukać?
Siddharth,
1
jackson-core: 2.2. + stał się dziedzictwem. więc musimy użyć databind: 2.7.0-rc3, adnotacji: 2.7.0-rc3 lub najnowszej wersji niż ta. Te 2 wystarczą, unikaj rdzenia jacksona: 2.2. +. W tym czasie dostałem trochę weryfikatora. podczas korzystania z wersji 2.7+ nie pokazuje tego błędu
anand krish
0

usuń niepotrzebny plik jar i spróbuj uruchomić. i jego praca dla mnie dodałem plik jar jcommons, a także inny plik jar jcommons.1.0.14, więc usuń jcommons i działa dla mnie

Jat Rahul
źródło
0

zapisz w pliku:

{Wildfly-home}\modules\system\layers\base\org\picketbox\main 

w zależności następnie: <module name="sun.jdk"/>

Eduardo Morales
źródło
-1

W moim przypadku otrzymywałem błąd weryfikacji ze śledzeniem poniżej stosu

jasperreports-server-cp-6.4.0-bin\buildomatic\build.xml:61: The following error occurred while executing this line:
TIB_js-jrs-cp_6.4.0_bin\jasperreports-server-cp-6.4.0-bin\buildomatic\bin\setup.xml:320: java.lang.VerifyError: (class: org/apache/commons/codec/binary/Base64OutputStream, method: <init> signature: (Ljava/io/OutputStream;ZI[B)V) Incompatible argument to function
    at com.jaspersoft.jasperserver.crypto.KeystoreManager.createKeystore(KeystoreManager.java:257)
    at com.jaspersoft.jasperserver.crypto.KeystoreManager.init(KeystoreManager.java:224)
    at com.jaspersoft.buildomatic.crypto.KeystoreTask.execute(KeystoreTask.java:64)
    at org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:292)
    at sun.reflect.GeneratedMethodAccessor4.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.apache.tools.ant.dispatch.DispatchUtils.execute(DispatchUtils.java:106)
    at org.apache.tools.ant.Task.perform(Task.java:348)
    at org.apache.tools.ant.taskdefs.Sequential.execute(Sequential.java:68)
    at org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:292)
    at sun.reflect.GeneratedMethodAccessor4.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.apache.tools.ant.dispatch.DispatchUtils.execute(DispatchUtils.java:106)
    at org.apache.tools.ant.Task.perform(Task.java:348)
    at org.apache.tools.ant.Target.execute(Target.java:435)
    at org.apache.tools.ant.helper.ProjectHelper2.parse(ProjectHelper2.java:169)
    at org.apache.tools.ant.taskdefs.ImportTask.importResource(ImportTask.java:222)
    at org.apache.tools.ant.taskdefs.ImportTask.execute(ImportTask.java:163)
    at org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:292)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.apache.tools.ant.dispatch.DispatchUtils.execute(DispatchUtils.java:106)
    at org.apache.tools.ant.Task.perform(Task.java:348)
    at org.apache.tools.ant.Target.execute(Target.java:435)
    at org.apache.tools.ant.helper.ProjectHelper2.parse(ProjectHelper2.java:180)
    at org.apache.tools.ant.ProjectHelper.configureProject(ProjectHelper.java:93)
    at org.apache.tools.ant.Main.runBuild(Main.java:826)
    at org.apache.tools.ant.Main.startAnt(Main.java:235)
    at org.apache.tools.ant.launch.Launcher.run(Launcher.java:280)
    at org.apache.tools.ant.launch.Launcher.main(Launcher.java:109)

Rozwiązałem problem poprzez usunięcie wpisu ścieżki klas dla commons-codec-1.3.jar, wystąpiła niezgodność wersji tego słoika z tym, który jest dostarczany z Jasperem.

Aashirwad Sinha
źródło