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ć.


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.


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?


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ę.


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.



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.



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).


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 ).


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

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.


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.


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ą.


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.


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.




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.


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.


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.


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.


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'

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


0

zapisz w pliku:

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

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


-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.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.