Как преодолеть ошибку VerifyError: Ожидание кадра карты стека для приложения JDK 7/8?

Я использую библиотеку модификации байт-кода ASM 5.0.3 с Tomcat 8 и JDK 8.

Я намерен успешно внедрить байт-код во все классы. Однако я столкнулся со следующей ошибкой:

java.lang.VerifyError: Expecting a stackmap frame at branch target 18
Exception Details:
  Location:
    com/sun/crypto/provider/SunJCE.getInstance()Lcom/sun/crypto/provider/SunJCE; @0: getstatic
  Reason:
    Expected stackmap frame at this location.
  Bytecode:
    0x0000000: b200 0bc7 000b bb00 3659 b700 0cb0 b200
    0x0000010: 0bb0 bf                                
  Exception Handler Table:
    bci [0, 18] => handler: 18
  Stackmap Table:
    append_frame(@14,Integer)

            at java.lang.Class.getDeclaredConstructors0(Native Method)
            at java.lang.Class.privateGetDeclaredConstructors(Unknown Source)
            at java.lang.Class.getConstructor0(Unknown Source)
            at java.lang.Class.newInstance(Unknown Source)
            at sun.security.jca.ProviderConfig$2.run(Unknown Source)
            at sun.security.jca.ProviderConfig$2.run(Unknown Source)
           ......Some more uninteresting lines in the stack trace.......
            at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
            at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
            at java.lang.reflect.Method.invoke(Unknown Source)
            at org.apache.catalina.startup.Bootstrap.load(Bootstrap.java:310)
            at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:484)

Ключевые части кода, которые я использовал для вызова методов ASM, следующие:

ClassWriter classWriter = new  ClassWriter(classReader, ClassWriter.COMPUTE_MAXS);

classReader.accept(myClassVisitor, ClassReader.EXPAND_FRAMES);

Приведенный выше код отлично работает с модификацией байт-кода приложения JDK 6. Ошибка появляется только для приложений JDK 7 и JDK 8.

Различные сообщения в блогах и сообщения stackoverflow указывают на использование флагов -XX:-UseSplitVerifier или -noverify. Однако это кажется краткосрочным обходным путем, особенно с учетом того, что флаг -XX:-UseSplitVerifier устарел в JDK 8. Я хотел бы получить постоянное решение, а не полагаться на флаг, который в конечном итоге не будет поддерживаться в будущих выпусках Java.

Заранее спасибо.

Изменить: В связи с любезным предложением Адама использовать COMPUTE_FRAMES вместо COMPUTE_MAXS эта ссылка ASM - java.lang.VerifyError: Исключение переполнения стека операндов суммирует ошибки до сих пор с COMPUTE_FRAMES. В настоящее время я не могу работать с JDK 7/8 ни с COMPUTE_MAXS, ни с COMPUTE_FRAMES.


person Ramesh Subramanian    schedule 29.12.2015    source источник


Ответы (2)


Используйте флаг ClassWriter#COMPUTE_FRAMES для стека. кадры карты, подлежащие пересчету. Верификатор байт-кода использует проверку типов (карту стека) из JDK 7 в, поэтому поэтому ваш код работает на JDK 6.

Обратите внимание, что (из COMPUTE_FRAMES JavaDoc):

ComputeFrames подразумевает вычислениеMaxs

person Adam Michalik    schedule 29.12.2015
comment
Привет, Адам! Должен ли я использовать ClassWriter.COMPUTE_FRAMES вместо ClassWriter.COMPUTE_MAXS? Или ClassWriter.COMPUTE_FRAMES в дополнение к вызову ClassWriter.COMPUTE_MAXS? - person Ramesh Subramanian; 29.12.2015
comment
Да, используйте COMPUTE_FRAMES вместо COMPUTE_MAXS. - person Adam Michalik; 29.12.2015
comment
Привет Адам: Спасибо за ваше продолжение до сих пор. Эта ссылка stackoverflow. com/questions/34495462/ обобщает (ошибочные) результаты с COMPUTE_FRAMES. - person Ramesh Subramanian; 29.12.2015

Я исправил проблему после расширения класса ClassWriter и переопределения метода getCommonSuperClass.

Пожалуйста, проверьте это ASM 5.0.3 с Java 1.8 неверный maxStack с Java.lang.VerifyError: Переполнение стека операндов

person Ramesh Subramanian    schedule 04.02.2016