java.lang.VerifyError: Несовместимые фреймы стековой карты в целевой ветви 421
Я получаю следующую ошибку при попытке развернуть файл войны.
SEVERE: WSSERVLET11: failed to parse runtime descriptor: java.lang.VerifyError: Inconsistent stackmap frames at branch target 421
Exception Details:
Location:
it/codegen/tbx/search/service/TravelBoxSearch.convertQuoteItemsEx(Ljava/lang/String;Ljava/lang/String;Ljava/util/List;)Lit/codegen/CGError; @421: getstatic
Reason:
Type 'it/codegen/CGResponse' (current frame, locals[5]) is not assignable to 'it/codegen/CGError' (stack map, locals[5])
Current Frame:
bci: @58
flags: { }
locals: { 'it/codegen/tbx/search/service/TravelBoxSearch', 'java/lang/String', 'java/lang/String', 'java/util/List', 'it/codegen/logging/TimeLogger', 'it/codegen/CGResponse', 'it/codegen/tbx/search/service/ShoppingBasket' }
stack: { 'it/codegen/tbx/search/service/ShoppingBasket' }
Stackmap Frame:
bci: @421
flags: { }
locals: { 'it/codegen/tbx/search/service/TravelBoxSearch', 'java/lang/String', 'java/lang/String', 'java/util/List', 'it/codegen/logging/TimeLogger', 'it/codegen/CGError', 'it/codegen/tbx/search/service/ShoppingBasket' }
stack: { }
Bytecode:
0x0000000: 013a 04b2 0127 9900 15bb 01a4 59b8 01a5
0x0000010: b601 a6b8 01a7 b701 a83a 04b8 0222 2cb6
0x0000020: 0223 bb07 d759 1402 1213 07d8 b707 d93a
0x0000030: 052a 2cb7 02b0 3a06 1906 c601 6b19 06b6
0x0000040: 02b1 3a07 1907 c601 452d c601 272d b902
0x0000050: 4e01 009a 011e bb01 cc59 b701 cd3a 082d
0x0000060: b902 3201 003a 0919 09b9 0233 0100 9900
0x0000070: 4a19 09b9 0234 0100 c002 353a 0a19 0ac6
0x0000080: 0036 190a b602 3ac6 002e 1908 bb00 3f59
0x0000090: b700 4019 0ab6 023a b602 a4b6 0042 190a
0x00000a0: b602 3ab6 023b b602 4cb6 0043 190a b602
0x00000b0: 3ab6 011d 57a7 ffb2 1907 b603 cfc6 0079
0x00000c0: 1907 b603 cfb9 0232 0100 3a09 1909 b902
0x00000d0: 3301 0099 0063 1909 b902 3401 00c0 02cf
0x00000e0: 3a0a 190a c600 4f19 08bb 003f 59b7 0040
0x00000f0: 190a b604 1db6 0042 190a b605 81b6 024c
0x0000100: b600 43b6 01e0 9900 2d19 08bb 003f 59b7
0x0000110: 0040 190a b604 1db6 0042 190a b605 81b6
0x0000120: 024c b600 43b6 01e1 c007 c819 0ab6 07da
0x0000130: b607 dba7 ff99 2a2b 2db6 07c7 3a09 1909
0x0000140: b602 8599 002b b200 29b8 0038 b200 3913
0x0000150: 07dc b600 3b2a 1909 1907 1906 b707 dd3a
0x0000160: 0519 0619 05b6 02ac c002 adb6 02c4 a700
0x0000170: 34b2 0029 b800 38b2 0039 1307 deb6 003b
0x0000180: 1905 1307 dfb6 027a a700 1ab2 0029 b800
0x0000190: 38b2 0039 1307 e0b6 003b 1905 1307 e1b6
0x00001a0: 027a a700 1ab2 0029 b800 38b2 0039 1303
0x00001b0: feb6 003b 1905 1307 e2b6 027a 1905 3a07
0x00001c0: b201 2799 0008 1904 b601 b619 07b0 3a0b
0x00001d0: b201 2799 0008 1904 b601 b619 0bbf
Exception Handler Table:
bci [27, 448] => handler: 462
bci [462, 464] => handler: 462
Stackmap Table:
append_frame(@27,Object[#3374])
full_frame(@103,{Object[#3339],Object[#3359],Object[#3359],Object[#3375],Object[#3374],Object[#3451],Object[#3623],Object[#3624],Object[#3478],Object[#3480]},{})
same_frame_extended(@181)
chop_frame(@184,1)
append_frame(@204,Object[#3480])
same_frame_extended(@307)
chop_frame(@310,1)
chop_frame(@366,1)
same_frame(@369)
same_frame(@395)
chop_frame(@418,1)
same_frame(@421)
same_frame(@444)
append_frame(@459,Object[#3451])
full_frame(@462,{Object[#3339],Object[#3359],Object[#3359],Object[#3375],Object[#3374]},{Object[#3344]})
full_frame(@475,{Object[#3339],Object[#3359],Object[#3359],Object[#3375],Object[#3374],Top,Top,Top,Top,Top,Top,Object[#3344]},{})
java.lang.VerifyError: Inconsistent stackmap frames at branch target 421
Exception Details:
Location:
it/codegen/tbx/search/service/TravelBoxSearch.convertQuoteItemsEx(Ljava/lang/String;Ljava/lang/String;Ljava/util/List;)Lit/codegen/CGError; @421: getstatic
Reason:
Type 'it/codegen/CGResponse' (current frame, locals[5]) is not assignable to 'it/codegen/CGError' (stack map, locals[5])
Current Frame:
bci: @58
flags: { }
locals: { 'it/codegen/tbx/search/service/TravelBoxSearch', 'java/lang/String', 'java/lang/String', 'java/util/List', 'it/codegen/logging/TimeLogger', 'it/codegen/CGResponse', 'it/codegen/tbx/search/service/ShoppingBasket' }
stack: { 'it/codegen/tbx/search/service/ShoppingBasket' }
Stackmap Frame:
bci: @421
flags: { }
locals: { 'it/codegen/tbx/search/service/TravelBoxSearch', 'java/lang/String', 'java/lang/String', 'java/util/List', 'it/codegen/logging/TimeLogger', 'it/codegen/CGError', 'it/codegen/tbx/search/service/ShoppingBasket' }
stack: { }
Bytecode:
0x0000000: 013a 04b2 0127 9900 15bb 01a4 59b8 01a5
0x0000010: b601 a6b8 01a7 b701 a83a 04b8 0222 2cb6
0x0000020: 0223 bb07 d759 1402 1213 07d8 b707 d93a
0x0000030: 052a 2cb7 02b0 3a06 1906 c601 6b19 06b6
0x0000040: 02b1 3a07 1907 c601 452d c601 272d b902
0x0000050: 4e01 009a 011e bb01 cc59 b701 cd3a 082d
0x0000060: b902 3201 003a 0919 09b9 0233 0100 9900
0x0000070: 4a19 09b9 0234 0100 c002 353a 0a19 0ac6
0x0000080: 0036 190a b602 3ac6 002e 1908 bb00 3f59
0x0000090: b700 4019 0ab6 023a b602 a4b6 0042 190a
0x00000a0: b602 3ab6 023b b602 4cb6 0043 190a b602
0x00000b0: 3ab6 011d 57a7 ffb2 1907 b603 cfc6 0079
0x00000c0: 1907 b603 cfb9 0232 0100 3a09 1909 b902
0x00000d0: 3301 0099 0063 1909 b902 3401 00c0 02cf
0x00000e0: 3a0a 190a c600 4f19 08bb 003f 59b7 0040
0x00000f0: 190a b604 1db6 0042 190a b605 81b6 024c
0x0000100: b600 43b6 01e0 9900 2d19 08bb 003f 59b7
0x0000110: 0040 190a b604 1db6 0042 190a b605 81b6
0x0000120: 024c b600 43b6 01e1 c007 c819 0ab6 07da
0x0000130: b607 dba7 ff99 2a2b 2db6 07c7 3a09 1909
0x0000140: b602 8599 002b b200 29b8 0038 b200 3913
0x0000150: 07dc b600 3b2a 1909 1907 1906 b707 dd3a
0x0000160: 0519 0619 05b6 02ac c002 adb6 02c4 a700
0x0000170: 34b2 0029 b800 38b2 0039 1307 deb6 003b
0x0000180: 1905 1307 dfb6 027a a700 1ab2 0029 b800
0x0000190: 38b2 0039 1307 e0b6 003b 1905 1307 e1b6
0x00001a0: 027a a700 1ab2 0029 b800 38b2 0039 1303
0x00001b0: feb6 003b 1905 1307 e2b6 027a 1905 3a07
0x00001c0: b201 2799 0008 1904 b601 b619 07b0 3a0b
0x00001d0: b201 2799 0008 1904 b601 b619 0bbf
Exception Handler Table:
bci [27, 448] => handler: 462
bci [462, 464] => handler: 462
Stackmap Table:
append_frame(@27,Object[#3374])
full_frame(@103,{Object[#3339],Object[#3359],Object[#3359],Object[#3375],Object[#3374],Object[#3451],Object[#3623],Object[#3624],Object[#3478],Object[#3480]},{})
same_frame_extended(@181)
chop_frame(@184,1)
append_frame(@204,Object[#3480])
same_frame_extended(@307)
chop_frame(@310,1)
chop_frame(@366,1)
same_frame(@369)
same_frame(@395)
chop_frame(@418,1)
same_frame(@421)
same_frame(@444)
append_frame(@459,Object[#3451])
full_frame(@462,{Object[#3339],Object[#3359],Object[#3359],Object[#3375],Object[#3374]},{Object[#3344]})
full_frame(@475,{Object[#3339],Object[#3359],Object[#3359],Object[#3375],Object[#3374],Top,Top,Top,Top,Top,Top,Object[#3344]},{})
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:348)
at com.sun.xml.ws.transport.http.DeploymentDescriptorParser.getImplementorClass(DeploymentDescriptorParser.java:615)
at com.sun.xml.ws.transport.http.DeploymentDescriptorParser.parseAdapters(DeploymentDescriptorParser.java:256)
at com.sun.xml.ws.transport.http.DeploymentDescriptorParser.parse(DeploymentDescriptorParser.java:179)
at com.sun.xml.ws.transport.http.servlet.WSServletContextListener.parseAdaptersAndCreateDelegate(WSServletContextListener.java:131)
at com.sun.xml.ws.transport.http.servlet.WSServletContainerInitializer.onStartup(WSServletContainerInitializer.java:65)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5280)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1559)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1549)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
И следующий компилятор thek, который я использую для компиляции кода
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.3</version>
<executions>
<execution>
<id>default-testCompile</id>
<phase>${testCompile.enable}</phase>
<goals>
<goal>testCompile</goal>
</goals>
</execution>
</executions>
<configuration>
<encoding>ISO-8859-1</encoding>
<source>1.8</source>
<target>1.8</target>
<useIncrementalCompilation>false</useIncrementalCompilation>
<testSource>1.8</testSource>
<testTarget>1.8</testTarget>
<!--<testExcludes>-->
<!--<exclude>**/test/*.java</exclude>-->
<!--</testExcludes>-->
</configuration>
</plugin>
Пожалуйста, посмотрите и ответьте, извините, я не специалист по форматированию.
4 ответа
После долгих усилий я нашел проблему. Были дублированные классы для CGError и CGResponse в двух разных библиотеках. Поэтому я думаю, что те, которые использовались во время компиляции, могут отличаться от тех, которые были загружены во время выполнения. В любом случае, устранение дублирующих классов помогло и решило эту проблему.
PS: не тратьте время на настройку -XX:-UseSplitVerifier, чтобы исправить эту проблему, если вы используете Java 1.8, даже если вы используете Java 1.7, старайтесь по возможности избегать использования этой конфигурации. Пожалуйста, пройдите по следующему URL, чтобы лучше понять проблему.
Есть ли лучшее объяснение фреймов стековой карты?
Объяснение в URL, как показано ниже.
Java требует, чтобы все загруженные классы были проверены, чтобы поддерживать безопасность песочницы и гарантировать безопасность кода для оптимизации. Обратите внимание, что это делается на уровне байт-кода, поэтому проверка не проверяет инварианты языка Java, а просто подтверждает, что байт-код имеет смысл в соответствии с правилами для байт-кода.
Помимо прочего, проверка байт-кода гарантирует, что инструкции правильно сформированы, что все переходы к действительным инструкциям внутри метода и что все инструкции работают со значениями правильного типа. Последнее место, где приходит карта стека.
Дело в том, что байт-код сам по себе не содержит явной информации о типе. Типы определяются неявно через анализ потока данных. Например, инструкция iconst создает целочисленное значение. Если вы храните его в слоте 1, этот слот теперь имеет int. Если поток управления сливается из кода, в котором вместо этого хранится число с плавающей запятой, слот теперь считается недопустимым типом, что означает, что вы не можете ничего сделать с этим значением, пока не перезапишите его.
Исторически верификатор байт-кода выводил все типы, используя эти правила потока данных. К сожалению, невозможно вывести все типы за один линейный проход через байт-код, потому что обратный переход может сделать недействительными уже выведенные типы. Классический верификатор решил эту проблему, перебирая код до тех пор, пока все не перестало меняться, что может потребовать нескольких проходов.
Однако проверка замедляет загрузку классов в Java. Oracle решила решить эту проблему, добавив новый, более быстрый верификатор, который может проверять байт-код за один проход. Для этого им требовалось, чтобы все новые классы, начиная с Java 7 (с Java 6 в переходном состоянии), содержали метаданные об их типах, чтобы байт-код мог быть проверен за один проход. Поскольку сам формат байт-кода не может быть изменен, эта информация о типе хранится отдельно в атрибуте с именем StackMapTable.
Простое хранение типа для каждого отдельного значения в каждой точке кода, очевидно, займет много места и будет очень расточительным. Чтобы сделать метаданные меньшими и более эффективными, они решили, что они должны перечислять только типы в позициях, которые являются целями прыжков. Если вы думаете об этом, это единственный раз, когда вам нужна дополнительная информация для проверки за один проход. Между целями прыжка весь поток управления является линейным, поэтому вы можете вывести типы между позициями, используя старые правила вывода.
Каждая позиция, в которой типы явно указаны, называется рамкой стековой карты. Атрибут StackMapTable содержит список кадров по порядку, хотя они обычно выражаются как отличие от предыдущего кадра для уменьшения размера данных. Если в методе нет фреймов, что происходит, когда поток управления никогда не присоединяется (т. Е. CFG является деревом), то атрибут StackMapTable можно полностью опустить.
Так что это основная идея о том, как работает StackMapTable и почему он был добавлен. Последний вопрос - как создается неявный начальный кадр. Ответ, конечно, заключается в том, что в начале метода стек операнда пуст и слоты локальной переменной имеют типы, заданные типами параметров метода, которые определяются из дескриптора метода.
Если вы привыкли к Java, есть несколько небольших различий в том, как типы параметров метода работают на уровне байт-кода. Во-первых, виртуальные методы имеют неявный this в качестве первого параметра. Во-вторых, логические значения, байты, символы и короткие значения не существуют на уровне байт-кода. Вместо этого все они реализованы как целые объекты за кулисами.
В моем случае эта проблема была связана с версией javassist, и я сообщил о потоке Error mocking Class, который содержит ссылку на SQLiteOpenHelper
С Уважением,
Для тех, кто использует Java-версии OpenJDK, в моем случае причиной этой проблемы было то, что у меня была проверка instanceof внутри тернарного оператора. Как только я заменил его правильным оператором if-else, эта ошибка исчезла. Когда я вернул его к тройному, вернулась ошибка. Моя JRE - это точка доступа 8.0.212.03 для справки.
Я тоже использую Nashorn, я не знаю, связано ли это с этим?
Я получил эту ошибку при использовании Eclipse jee 2019-12-R. Изменение версии Eclipse исправило это.