2015-12-29 1 views
2

Я использую библиотеку модификации байт-кода ASM 5.0.3 с Tomcat 8 и JDK 8.Как я могу преодолеть «VerifyError: Expecting framemap frame» для приложения JDK 7/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 flags. Однако это похоже на краткосрочное обходное решение, особенно учитывая, что флаг -XX: -UseSplitVerifier устарел в JDK 8. Я хотел бы получить постоянное решение, а не полагаться на флаг, который в конечном итоге не будет поддерживаться в будущих выпусках Java.

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

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

ответ

3

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

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

computeFrames implies computeMaxs

+1

Привет Адам, Должен ли я использовать ClassWriter.COMPUTE_FRAMES ** вместо ** ClassWriter.COMPUTE_MAXS? Или это ClassWriter.COMPUTE_FRAMES ** в дополнение к ** вызову ClassWriter.COMPUTE_MAXS? –

+0

Да, используйте 'COMPUTE_FRAMES' вместо просто' COMPUTE_MAXS'. –

+0

Привет Адам: Спасибо за ваше продолжение. Эта ссылка http://stackoverflow.com/questions/34495462/asm-java-lang-verifyerror-operand-stack-overflow-exception суммирует (ошибочные) результаты до сих пор с помощью команды COMPUTE_FRAMES. –

Смежные вопросы