繁体   English   中英

字节码验证失败, java.lang.VerifyError: Expecting a stackmap frame at branch target 11 。 分支目标 11 是什么意思?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM