5

我遇到了一些麻烦,运行一个简单的主程序与番石榴库。与ASM字节码检测功能不兼容的参数

我已经仪表类使用我的代码从这里获取方法的参数:Java method parameters values in ASM

的问题是,虽然该代码适用于小型项目(河内又名塔),与番石榴我有错误,例外。

特别地,测试Joiner.join方法时,我有这样的错误:

Exception in thread "Jalen Agent" java.lang.VerifyError: (class: com/google/common/base/Joiner, method: withKeyValueSeparator signature: (Ljava/lang/String;)Lcom/google/common/base/Joiner$MapJoiner;) Incompatible argument to function 
at Main.joinBench(Main.java:42) 
at Main.main(Main.java:20) 

并采用-noverify运行示例的情况下,我有一个例外:

Exception in thread "Jalen Agent" java.lang.ArrayIndexOutOfBoundsException: 1 
at com.google.common.base.Joiner.<init>(Joiner.java) 
at com.google.common.base.Joiner.on(Joiner.java:71) 
at Main.joinBench(Main.java:42) 
at Main.main(Main.java:20) 

字节码的方法是一致的:

public static com.google.common.base.Joiner on(java.lang.String); 
     Code: 
     0: bipush  1 
     2: anewarray  #4     // class java/lang/Object 
     5: astore_1  
     6: aload_1  
     7: bipush  0 
     9: aload_0  
     10: aastore  
     11: ldc   #20     // int 369 
     13: ldc   #21     // String com/google/common/base/Joiner 
     15: ldc   #22     // String on 
     17: aload_1  
     18: invokestatic #28     // Method jalen/MethodStats.onMethodEntry:(ILjava/lang/String;Ljava/lang/String;[Ljava/lang/Object;)V 
     21: new   #2     // class com/google/common/base/Joiner 
     24: dup   
     25: aload_0  
     26: invokespecial #32     // Method "<init>":(Ljava/lang/String;)V 
     29: ldc   #20     // int 369 
     31: invokestatic #36     // Method jalen/MethodStats.onMethodExit:(I)V 
     34: areturn 

我知道错误可能与图书馆有关ies版本,但主要的java程序是针对检测过的库编译的,并使用库的同一个罐子运行。

为什么会发生这种情况的任何想法?以及如何解决?

谢谢:)

编辑

这里有方法withKeyValueSeparator的字节码前和后插

原始字节码:

public com.google.common.base.Joiner$MapJoiner withKeyValueSeparator(java.lang.String); 
Code: 
    0: new   #33     // class com/google/common/base/Joiner$MapJoiner 
    3: dup   
    4: aload_0  
    5: aload_1  
    6: aconst_null 
    7: invokespecial #34     // Method com/google/common/base/Joiner$MapJoiner."<init>":(Lcom/google/common/base/Joiner;Ljava/lang/String;Lcom/google/common/base/Joiner$1;)V 
    10: areturn 

仪器化的字节码:

public com.google.common.base.Joiner$MapJoiner withKeyValueSeparator(java.lang.String); 
Code: 
    0: bipush  1 
    2: anewarray  #4     // class java/lang/Object 
    5: astore_1  
    6: aload_1  
    7: bipush  1 
    9: aload_1  
    10: aastore  
    11: ldc   #199    // int 390 
    13: ldc   #21     // String com/google/common/base/Joiner 
    15: ldc   #200    // String withKeyValueSeparator 
    17: aload_1  
    18: invokestatic #28     // Method jalen/MethodStats.onMethodEntry:(ILjava/lang/String;Ljava/lang/String;[Ljava/lang/Object;)V 
    21: new   #8     // class com/google/common/base/Joiner$MapJoiner 
    24: dup   
    25: aload_0  
    26: aload_1  
    27: aconst_null 
    28: invokespecial #203    // Method com/google/common/base/Joiner$MapJoiner."<init>":(Lcom/google/common/base/Joiner;Ljava/lang/String;Lcom/google/common/base/Joiner$1;)V 
    31: ldc   #199    // int 390 
    33: invokestatic #36     // Method jalen/MethodStats.onMethodExit:(I)V 
    36: areturn 

下面是木匠类的完整的字节码:

原文:http://pastebin.com/VsccVX18

仪表:http://pastebin.com/xtke1a8y

+0

难道你'-v'标志添加到您的'javap'命令?前者打印一些其他有用的信息,可以帮助。 – Xyene

回答

0

首先,我不明白为什么这应该是有关库的版本。看起来字节码没有正确检测,导致验证失败,如果使用-noverify,则会出现异常。

关于验证错误,它表明Joiner.withKeyValueSeparator()中有错误。此方法的代码尝试调用具有不兼容方法参数的另一个方法。你可以给withKeyValueSeparator()方法的检测字节码吗? (以及非仪器化的)

用-noverify看到的错误发生在Joiner的构造函数中,Joiner.on()方法似乎没有错。再次,你可以发布Joiner的字节码。方法? (仪器化和非仪器化)

+0

嗨,谢谢你的见解:)。我用KeyValueSeparator添加了方法的字节码,包括原始的和检测的。我还添加了该类的pastebin(也在2版本中)。 – Adel

1

withKeyValueSeparator的原始代码将其一系列参数传递给MapJoiner构造函数。您正在添加将数组存储在本地变量表的第二个插槽中的检测代码(使用astore_1)。这将覆盖第一个参数withKeyValueSeparator,这是一个String。 (局部变量表的第一时隙是MapJoiner实例本身,又名this。),所以当原来的功能的代码试图传递对象的局部变量表的构造的第二时隙,存在“不兼容的变量”错误。

为了解决这个问题,你应该在分配您的阵列中的局部变量表的新插槽; this answer概述了如何。