How do I overcome the "VerifyError:Expecting a stackmap frame" for a JDK 7/8 application?
How do I overcome the "VerifyError:Expecting a stackmap frame" for a JDK 7/8 application?
我正在使用 Tomcat 8 和 JDK 8 的 ASM 5.0.3 字节码修改库。
我的目的是将字节码成功注入所有 类。但是,我遇到了以下错误:
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.run(Unknown Source)
at sun.security.jca.ProviderConfig.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 应用程序显示。
各种博客帖子和 Whosebug 帖子都指向使用 -XX:-UseSplitVerifier 或 -noverify 标志。然而,这似乎是一个短期的解决方法,特别是考虑到 -XX:-UseSplitVerifier 标志在 JDK 8 中被弃用。我想实现一个永久的解决方案,而不是依赖一个将来最终不受支持的标志Java 发布。
提前谢谢你。
编辑: 参考 Adam 关于使用 COMPUTE_FRAMES
而不是 COMPUTE_MAXS
的善意建议,此 link ASM - java.lang.VerifyError: Operand stack overflow Exception 总结到目前为止 COMPUTE_FRAMES
的错误。目前,我无法通过 COMPUTE_MAXS
或 COMPUTE_FRAMES
.
在 JDK 7/8 上取得进展
使用 ClassWriter#COMPUTE_FRAMES
flag for the stack map frames to be recomputed. The bytecode verifier uses typechecker (stack map) from JDK 7 on,这就是为什么您的代码适用于 JDK 6.
请注意(来自 COMPUTE_FRAMES
JavaDoc):
computeFrames implies computeMaxs
我在扩展 ClassWriter class 并覆盖方法 getCommonSuperClass 后解决了这个问题。
请检查这个
我正在使用 Tomcat 8 和 JDK 8 的 ASM 5.0.3 字节码修改库。
我的目的是将字节码成功注入所有 类。但是,我遇到了以下错误:
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.run(Unknown Source)
at sun.security.jca.ProviderConfig.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 应用程序显示。
各种博客帖子和 Whosebug 帖子都指向使用 -XX:-UseSplitVerifier 或 -noverify 标志。然而,这似乎是一个短期的解决方法,特别是考虑到 -XX:-UseSplitVerifier 标志在 JDK 8 中被弃用。我想实现一个永久的解决方案,而不是依赖一个将来最终不受支持的标志Java 发布。
提前谢谢你。
编辑: 参考 Adam 关于使用 COMPUTE_FRAMES
而不是 COMPUTE_MAXS
的善意建议,此 link ASM - java.lang.VerifyError: Operand stack overflow Exception 总结到目前为止 COMPUTE_FRAMES
的错误。目前,我无法通过 COMPUTE_MAXS
或 COMPUTE_FRAMES
.
使用 ClassWriter#COMPUTE_FRAMES
flag for the stack map frames to be recomputed. The bytecode verifier uses typechecker (stack map) from JDK 7 on,这就是为什么您的代码适用于 JDK 6.
请注意(来自 COMPUTE_FRAMES
JavaDoc):
computeFrames implies computeMaxs
我在扩展 ClassWriter class 并覆盖方法 getCommonSuperClass 后解决了这个问题。
请检查这个