当Class加载时,Java 1.8字节代码验证失败.Below是Class 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)
答案 0 :(得分:0)
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问题”以找到更具体的解决方案。