java.lang.VerifyError: Oczekiwano ramki stosu w gałęzi docelowej JDK 1.7

88

Po aktualizacji do JDK 1.7 otrzymuję poniższy wyjątek:

java.lang.VerifyError: Expecting a stackmap frame at branch target 71 in method com.abc.domain.myPackage.MyClass$JaxbAccessorM_getDescription_setDescription_java_lang_String.get(Ljava/lang/Object;)Ljava/lang/Object; at offset 20
    at java.lang.Class.getDeclaredConstructors0(Native Method)
    at java.lang.Class.privateGetDeclaredConstructors(Class.java:2413)
    at java.lang.Class.getConstructor0(Class.java:2723)
    at java.lang.Class.newInstance0(Class.java:345)
    at java.lang.Class.newInstance(Class.java:327)
    at com.sun.xml.internal.bind.v2.runtime.reflect.opt.OptimizedAccessorFactory.instanciate(OptimizedAccessorFactory.java:184)
    at com.sun.xml.internal.bind.v2.runtime.reflect.opt.OptimizedAccessorFactory.get(OptimizedAccessorFactory.java:129)
    at com.sun.xml.internal.bind.v2.runtime.reflect.Accessor$GetterSetterReflection.optimize(Accessor.java:384)
    at com.sun.xml.internal.bind.v2.runtime.property.SingleElementLeafProperty.<init>(SingleElementLeafProperty.java:72)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:525)
    at com.sun.xml.internal.bind.v2.runtime.property.PropertyFactory.create(PropertyFactory.java:113)
    at com.sun.xml.internal.bind.v2.runtime.ClassBeanInfoImpl.<init>(ClassBeanInfoImpl.java:166)
    at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl.getOrCreate(JAXBContextImpl.java:494)
    at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl.<init>(JAXBContextImpl.java:311)
    at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl.<init>(JAXBContextImpl.java:126)
    at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl$JAXBContextBuilder.build(JAXBContextImpl.java:1148)
    at com.sun.xml.internal.bind.v2.ContextFactory.createContext(ContextFactory.java:130)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:248)
    at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:235)
    at javax.xml.bind.ContextFinder.find(ContextFinder.java:445)
    at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:637)
    at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:584)
    at com.abc.domain.myPackage.MyClass.marshalFacetsTest(MyClass.java:73)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:80)
    at org.testng.internal.Invoker.invokeMethod(Invoker.java:714)
    at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:901)
    at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:1231)
    at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:128)
    at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:111)
    at org.testng.TestRunner.privateRun(TestRunner.java:767)
    at org.testng.TestRunner.run(TestRunner.java:617)
    at org.testng.SuiteRunner.runTest(SuiteRunner.java:334)
    at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:329)
    at org.testng.SuiteRunner.privateRun(SuiteRunner.java:291)
    at org.testng.SuiteRunner.run(SuiteRunner.java:240)
    at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52)
    at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:86)
    at org.testng.TestNG.runSuitesSequentially(TestNG.java:1203)
    at org.testng.TestNG.runSuitesLocally(TestNG.java:1128)
    at org.testng.TestNG.run(TestNG.java:1036)
    at org.testng.remote.RemoteTestNG.run(RemoteTestNG.java:111)
    at org.testng.remote.RemoteTestNG.initAndRun(RemoteTestNG.java:204)
    at org.testng.remote.RemoteTestNG.main(RemoteTestNG.java:175)
Jan
źródło

Odpowiedzi:

171

Java 7 wprowadziła bardziej rygorystyczną weryfikację i nieco zmieniła format klasy - tak, aby zawierała mapę stosu używaną do weryfikacji poprawności kodu. Wyjątek, który widzisz, oznacza, że ​​jakaś metoda nie ma prawidłowej mapy stosu.

Winna może być zarówno wersja Java, jak i instrumentacja kodu bajtowego. Zwykle oznacza to, że biblioteka używana przez aplikację generuje nieprawidłowy kod bajtowy, który nie przechodzi dokładniejszej weryfikacji. Tak więc programista nie może zrobić nic innego niż zgłoszenie tego jako błędu w bibliotece.

Aby obejść ten problem, możesz dodać -noverifyargumenty maszyny JVM, aby wyłączyć weryfikację. W Javie 7 można było również -XX:-UseSplitVerifierużyć mniej rygorystycznej metody weryfikacji, ale ta opcja została usunięta w Javie 8.

Mirko Adari
źródło
1
Ale co oznacza -XX: -UseSplitVerifier ?? Spojrzałem na wyjaśnienie Oracle, gdzie jest napisane: „Użyj nowego narzędzia do sprawdzania typów z atrybutami StackMapTable”. Nie rozumiem.
John
2
Więc jeśli widzę ten błąd: czy to błąd w JVM czy w moim kodzie?
bentolor
4
ta odpowiedź nie jest poprawna w dłuższej perspektywie, a może już nie jest ważna, ponieważ Oracle wycofuje tę opcję. Jestem dotknięty tym błędem (z innym kodem) i szukam sposobu na przebudowę map stosu
ZiglioUK
2
dla testu jednostkowego musisz przekazać argumenty we wtyczce surefire. Rozwiązano problem z kompilatorami java 7 i 8: <plugin> <groupId> org.apache.maven.plugins </groupId> <artifactId> maven-surefire-plugin </artifactId> <version> 2.18.1 </ version > <configuration> <argLine> -noverify -XX: -UseSplitVerifier </argLine> </configuration> </plugin>
Antoine Wils
2
miałem ten sam problem, ale po dodaniu -noverify to naprawdę zadziałało. dzięki.
Praveen Kumar Mekala
15

Jeśli używasz XX:-UseSplitVerifierjęzyka Java 1.8, usuń i użyj -noverifywe właściwościach maszyny JVM.

Anand Kumar KK
źródło
8

Napotkałem ten problem i spróbowałem użyć flagi, -noverifyktóra naprawdę działa. Dzieje się tak z powodu nowego weryfikatora kodu bajtowego. Więc flaga powinna naprawdę działać. Używam JDK 1.7.

Uwaga: to nie zadziała, jeśli używasz JDK 1.8

Charan Raj
źródło
3
U mnie za pomocą flagi naprawiono wykonywanie naszych testów jednostkowych systemu Android przy użyciu środowiska JRE 8 jako środowiska uruchomieniowego.
ubuntudroid
2
-noverify działało również dla mnie na Javie 8. Używam gradle dla Androida, więc musiałem umieścić flagę -noverify tam, gdzie jest to określone w stackoverflow.com/a/37593189/2848676
Michael Osofsky
gdzie ustawiłeś -noverify? Ustawiłem go jako MAVEN_OPTS, ale to nie działa dla mnie
dev
@Sara Antunez, Dodaj to do pliku build.gradle modułów aplikacji w zamknięciu Androida. android {.... testOptions {unitTests.all {jvmArgs '-noverify'}}}
GrokkingDroid
2

Jedyną różnicą między plikami powodującymi problem jest ósmy bajt pliku

CA FE BA BE 00 00 00 33 - Java 7

vs.

CA FE BA BE 00 00 00 32 - Java 6

Ustawienie -XX:-UseSplitVerifierrozwiązuje problem. Jednak przyczyną tego problemu jest https://bugs.eclipse.org/bugs/show_bug.cgi?id=339388

Kunin
źródło
2

Przekaż -noverifyargument JVM do zadania testowego. Jeśli używasz gradle, build.gradlemożesz mieć coś takiego:

test {
  jvmArgs "-noverify"
}
Lew
źródło
0

Ten BŁĄD może się zdarzyć, gdy używasz Mockito do kpiny z klas końcowych .

Zamiast tego rozważ użycie Mockito inline lub Powermock.

nhoxbypass
źródło
-1

Przepraszam za kopanie, ale napotkałem ten sam problem i znalazłem prostsze rozwiązanie.

W opcjach kompilatora Java należy odznaczyć opcję „Zachowaj nieużywane (nigdy nie odczytywane) zmienne lokalne”, aby nie było potrzeby zmiany docelowej wersji JVM.

Wygląda na to, że jest to błąd w starszych wersjach Eclipe.

scoro
źródło
to nie działa dla mnie. Oto streszczenie
ZiglioUK
3
OP nie wspomina o Eclipse. Może nawet go nie używa.
Don Branson
-3

Jeśli sam tworzysz kod, problem ten można rozwiązać, podając „-target 1.5” kompilatorowi java (lub ustawiając odpowiednią opcję w swoim IDE lub konfiguracji kompilacji).

jrajp2184
źródło
-11

ten link jest pomocny. java.lang.VerifyError: Oczekiwano ramki stosu mapy

najprostszym sposobem jest zmiana środowiska JRE na 6.

yuxiaomin
źródło
7
obniżanie wersji, gdy prosty argument JVM może naprawić? Wątpię w twoją definicję prostoty.
Visionary Software Solutions,
1
Chociaż może to teoretycznie odpowiedzieć na pytanie, lepiej byłoby zawrzeć tutaj zasadnicze części odpowiedzi i podać link do odniesienia.
Joachim Sauer
To jest obejście. Jak powiedział Joachim, może to działać - ale nie definiuje problemu ani nie pomaga zespołom lub bazom kodu, które muszą używać Java 7
Crowie
W połączonym pytaniu jest wiele odpowiedzi. Obniżenie poziomu to tylko jedna z wymienionych opcji.
Ogre Psalm 33