java.lang.VerifyError: ожидание фрейма карты стека в целевой ветви JDK 1.7

88

После обновления до JDK 1.7 я получаю исключение ниже:

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)
Джон
источник

Ответы:

171

В Java 7 была введена более строгая проверка и немного изменен формат класса, чтобы он содержал карту стека, используемую для проверки правильности кода. Исключение, которое вы видите, означает, что у некоторого метода нет действительной карты стека.

В этом могут быть виноваты как версия Java, так и инструментарий байт-кода. Обычно это означает, что библиотека, используемая приложением, генерирует недопустимый байт-код, который не проходит более строгую проверку. Таким образом, разработчик не может сделать ничего, кроме сообщения об ошибке в библиотеке.

В качестве обходного пути вы можете добавить -noverifyаргументы JVM, чтобы отключить проверку. В Java 7 также можно было -XX:-UseSplitVerifierиспользовать менее строгий метод проверки, но в Java 8 этот параметр был удален.

Мирко Адари
источник
1
Но что означает -XX: -UseSplitVerifier ?? Я посмотрел на объяснение Oracle, в нем говорится: «Используйте средство проверки нового типа с атрибутами StackMapTable». Я не понял.
Джон
2
Итак, если я увижу эту ошибку: это ошибка JVM или моего кода?
бентолор
4
этот ответ недействителен в долгосрочной перспективе или, возможно, уже давно, поскольку Oracle не рекомендует эту опцию. Я поражен этой ошибкой (с другим кодом), и я ищу способ предотвратить перестройку стековых карт
ZiglioUK
2
для модульного теста вы должны передать аргументы в плагин surefire. Это исправило проблему для компиляторов java 7 и 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
Я столкнулся с той же проблемой, но после добавления -noverify это действительно сработало для меня. Спасибо.
Правин Кумар Мекала
15

Если вы используете java 1.8, удалите XX:-UseSplitVerifierи используйте -noverifyв свойствах JVM.

Ананд Кумар К.К.
источник
8

Я столкнулся с этой проблемой и попробую использовать флаг, -noverifyкоторый действительно работает. Это из-за нового верификатора байт-кода. Так что флаг действительно должен работать. Я использую JDK 1.7.

Примечание: это не сработает, если вы используете JDK 1.8.

Чаран Радж
источник
3
Для меня использование флага исправлено при выполнении наших модульных тестов Android с использованием JRE 8 в качестве среды выполнения.
ubuntudroid
2
-noverify также работал у меня на Java 8. Я использую gradle для Android, поэтому мне пришлось поставить флаг -noverify там, где это указано в stackoverflow.com/a/37593189/2848676
Майкл Ософски
где ставили -noverify? Я установил его как MAVEN_OPTS, но у меня он не работает
dev
@Sara Antunez, в файле build.gradle модулей вашего приложения при закрытии Android добавьте это. android {.... testOptions {unitTests.all {jvmArgs '-noverify'}}}
GrokkingDroid
2

Единственное различие между файлами, вызывающими проблему, - это 8-й байт файла.

CA FE BA BE 00 00 00 33 - Java 7

vs.

CA FE BA BE 00 00 00 32 - Java 6

Настройка -XX:-UseSplitVerifierрешает проблему. Однако причиной этой проблемы является https://bugs.eclipse.org/bugs/show_bug.cgi?id=339388.

Кунин
источник
2

Передайте -noverifyаргумент JVM своей тестовой задаче. Если вы используете gradle, у build.gradleвас может быть что-то вроде:

test {
  jvmArgs "-noverify"
}
Лео
источник
0

Эта ОШИБКА может произойти, когда вы используете Mockito для имитации финальных классов .

Вместо этого рассмотрите возможность использования встроенного Mockito или Powermock.

nhoxbypass
источник
-1

Извините за копание, но я столкнулся с той же проблемой и нашел более простое решение.

В параметрах компилятора Java необходимо снять флажок «Сохранять неиспользуемые (никогда не читаемые) локальные переменные», чтобы не менять целевую версию JVM.

Похоже, это ошибка в старых версиях Eclipe.

скоро
источник
у меня это не работает. Вот суть моей ошибки: gist.github.com/ZiglioNZ/bd1d7d424727b3f26c64
ZiglioUK
3
OP не упоминает Eclipse. Он может даже не использовать это.
Дон Брэнсон
-3

Если вы создаете код самостоятельно, эту проблему можно решить, указав "-target 1.5" компилятору java (или установив соответствующий параметр в вашей среде IDE или конфигурации сборки).

jrajp2184
источник
-11

эта ссылка полезна. java.lang.VerifyError: ожидается фрейм карты стека

Самый простой способ - изменить JRE на 6.

Юсяомин
источник
7
переход на более раннюю версию, когда простой аргумент JVM может исправить? Я сомневаюсь в вашем простом определении.
Visionary Software Solutions
1
Хотя теоретически это может дать ответ на вопрос, было бы предпочтительнее включить сюда основные части ответа и предоставить ссылку для справки.
Joachim Sauer
Это работа. Как сказал Иоахим, это может сработать, но это не определяет проблему или помощь командам или кодовым базам, которые должны использовать Java 7
Crowie
В связанном вопросе есть несколько ответов. Понижение версии - это только один из перечисленных вариантов.
Ogre Psalm33