[英]java.lang.VerifyError: Expecting a stackmap frame at branch target
[英]Byte Code Verification failing with java.lang.VerifyError: Expecting a stackmap frame at branch target 11 . What does branch target 11 means?
加载类时,Java 1.8 字节码验证失败。下面是加载失败的类 SnaControl 的构造函数。 使用 javac 1.6 编译时运行良好
public com.lucent.oms.sna.SnaControl();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=2, locals=1, args_size=1
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: aload_0
5: aconst_null
6: putfield #2 // Field snaName:Ljava/lang/String;
9: aload_0
10: iconst_0
11: putfield #3 // Field snaHealthStatus:Z
14: aload_0
15: aconst_null
16: putfield #4 // Field snaPOA:Lorg/omg/PortableServer/POA;
19: aload_0
20: aconst_null
21: putfield #5 // Field m_corbaUtil:Lcom/lucent/oms/almapapi/util/CorbaUtil;
24: aload_0
25: aconst_null
26: putfield #6 // Field exSnmp:Lcom/lucent/oms/exsnmp/ExSnmpAdapter;
29: aload_0
30: putstatic #7 // Field snaControlObj:Lcom/lucent/oms/sna/SnaControl;
33: return
LineNumberTable:
line 35: 0
line 25: 4
line 26: 9
line 28: 14
line 32: 19
line 33: 24
line 36: 29
line 37: 33
LocalVariableTable:
Start Length Slot Name Signature
0 34 0 this Lcom/lucent/oms/sna/SnaControl;
错误 :
Exception in thread "main" java.lang.VerifyError: Expecting a stackmap
frame at branch target 11 Exception Details: Location:
com/lucent/oms/sna/SnaControl.<init>()V @4: ifnonnull Reason:
Expected stackmap frame at this location. Bytecode:
0x0000000: b201 7b59 c700 0757 b801 8503 324c 2ab7
0x0000010: 0001 2a01 b500 022a 03b5 0003 2a01 b500
0x0000020: 042a 01b5 0005 2a01 b500 062a b300 072b
0x0000030: 0304 54b1
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:264)
at com.lucent.oms.infra.SubsysCtrl.GenericSubsysCtrlHandler.<init>(GenericSubsysCtrlHandler.java:50)
at com.lucent.oms.infra.SubsysCtrl.SubsysCtrlHandler.<init>(SubsysCtrlHandler.java:36)
at com.lucent.oms.infra.SubsysCtrl.SimpleSubsystem.initSubsysCtrlHandler(SimpleSubsystem.java:300)
at com.lucent.oms.infra.SubsysCtrl.SimpleSubsystem.<init>(SimpleSubsystem.java:228)
at com.lucent.oms.infra.SubsysCtrl.SimpleSubsystem.main(SimpleSubsystem.java:1442)
VerifyError
包含有问题的字节码作为十六进制转储。 当我解码它时,我得到:
0 getstatic [379]
3 dup
4 ifnonnull @7
7 pop
8 invokestatic [389]
11 iconst_0
12 aaload
13 astore_1
14 aload_0
15 invokespecial [1]
18 aload_0
19 aconst_null
20 putfield [2]
23 aload_0
24 iconst_0
25 putfield [3]
28 aload_0
29 aconst_null
30 putfield [4]
33 aload_0
34 aconst_null
35 putfield [5]
38 aload_0
39 aconst_null
40 putfield [6]
43 aload_0
44 putstatic [7]
47 aload_1
48 iconst_0
49 iconst_1
50 bastore
51 return
这显然与您发布的原始代码不同,但具有可识别的模式。 我插入了空行,以便在新代码中更容易识别您的原始代码。 很明显,您的代码已经被一个工具检测到,在方法进入和方法退出时添加了一个动作。
问题是您的原始代码是无分支的,而新代码包含从位置4
到位置11
( 4+7
) 的条件分支。 您应该在VerifyError
的消息中识别这些部分:“在分支目标11
处期待堆栈图帧”和“ @4: ifnonnull
”。 因此,错误不在于您的原始代码,而在于字节码检测工具注入的代码。
从类文件v51
(Java 7) 开始,堆栈映射成为强制性的,而对于v50
(Java 6),如果这些堆栈映射发生错误,验证器将切换到旧的遗留验证器。 这旨在为更新工具提供时间,这些工具无法处理堆栈映射,反而导致更多人不了解这种无能。
那么实际后果是什么呢? 您必须识别执行无效检测的工具并更新它(希望存在更新)。 这可能包括负责资源注入、AOP 或分析的框架。 通常,这些工具建立在较低级别的字节码工程库上,并且仅更新该库可能就足够了。 好吧,如果您确定了负责的库,您可以搜索“库名 + java8 问题”以找到更具体的解决方案。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.