java - 与 ASM 字节码检测功能不兼容的参数

标签 java bytecode java-bytecode-asm bytecode-manipulation verifyerror

我在使用 Guava 库运行一个简单的主程序时遇到了一些问题。

我已使用此处的代码对类进行检测以获取方法参数:Java method parameters values in ASM

问题是,虽然代码适用于小型项目(又名汉诺塔),但使用 Guava 我会遇到错误和异常。

特别是在测试 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

我知道错误可能与库版本有关,但主要 java 程序是针对检测库编译的,并使用库的相同 jar 运行。

关于为什么会发生这种情况的任何想法?又如何解决?

谢谢:)

编辑

这是检测前后 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 

这里是 joiner 类的完整字节码:

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

检测:http://pastebin.com/xtke1a8y

最佳答案

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

要解决这个问题,您应该在局部变量表中为您的数组分配一个新槽; this answer概述了方法。

关于java - 与 ASM 字节码检测功能不兼容的参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14155614/

相关文章:

java - 当本地目录有任何内容时,SFTP 入站 channel 适配器不复制文件

java - 如何设计 Spring MVC REST 服务?

java - ASM 5中visitMethodInsn的 "itf"参数说明

java - 如何使用 ASM 来欺骗 HelloWorld.scala?已加载到 JVM 但未找到?

java - 如何在 java 代码中重现 eclipse 的运行参数?

Java为每个数据库行创建唯一的线程

java - 由 native 库处理解密的加密类文件

java - 从 C 源代码到 Java 字节码?

python - Web2Py 中的每次调用都会解释代码吗?

java - 在 java ASM 中访问私有(private)内部类