java - 使用 ASM (5.x) : howto? 在字节代码中检测运行时的递归方法调用

标签 java bytecode java-bytecode-asm

问题如下;该方法在 Java 代码中是:

Rule foo()
{
    return sequence(foo(), x());
}

这将引发一个当然应该避免的解析循环;然而,这是是合法的:

Rule foo()
{
    return sequence(x(), foo());
}

现在,在代码的其他地方我可以访问 RuleMethod,这是一个扩展 MethodNode 的类,因此我可以访问以下信息:

  • ruleMethod.name: foo; (在 MethodNode 中定义)
  • ruleMethod.desc:()Lorg/parboiled/Rule;(在MethodNode中定义)
  • ruleMethod.ownerClass:com.github.fge.grappa.experiments.SelfReferringRule.MyParser(定义在RuleMethod

上面第一个代码摘录的字节码如下:

Method 'foo':
 0    L0
 1     ALOAD 0
 2     ALOAD 0
 3     INVOKEVIRTUAL com/github/fge/grappa/experiments/SelfReferringRule$MyParser.foo ()Lorg/parboiled/Rule;
 4     ALOAD 0
 5     INVOKEVIRTUAL com/github/fge/grappa/experiments/SelfReferringRule$MyParser.x ()Lorg/parboiled/Rule;
 6     ICONST_0
 7     ANEWARRAY java/lang/Object
 8     INVOKEVIRTUAL com/github/fge/grappa/experiments/SelfReferringRule$MyParser.sequence (Ljava/lang/Object;Ljava/lang/Object;[Ljava/lang/Object;)Lorg/parboiled/Rule;
 9     ARETURN
10    L1

这意味着我掌握了所有可用的信息,至少在上面的字节码中,foo()第一个参数 sequence() 调用,因为构造函数接受三个参数并且堆栈上有三个元素。

但是我当然不能在运行时“目视检查”。因此我需要一种方法来做到这一点......

看起来我需要的是一个 MethodVisitor 和一些 visitInsn(),然后查看有哪些参数并适本地检测...

但我完全不知道从哪里开始;在网上搜索似乎只给出了如何修改字节码的例子,没有检测到这种情况:/

我从哪里开始?

最佳答案

使用 tree api 分析通常要容易得多因为它允许您轻松回溯并为流分析提供支持。

如果我正确理解您的问题,那么您需要做的(如果您希望支持的只是简单的案例,例如您的示例)就是从序列调用向后扫描。如您所知,代码编译堆栈上的内容必须是有效的,所以只需倒数三个方法调用/字段获取/等。

如果您想支持更复杂的场景,即通过分支语句将输入分配给变量,您将需要某种流分析。

关于java - 使用 ASM (5.x) : howto? 在字节代码中检测运行时的递归方法调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28172793/

相关文章:

java - 路由器/经销商代理不传送消息

jvm - 有没有办法关闭 JIT 编译器,这样做是否会影响性能?

java - 改变 Java 中静态方法的行为 - 字节码操作

java - 在 Java 中存储唯一排序值的最有效方法(最佳性能和最少 gc)是什么?

java - 用于从 pom.xml 下载依赖项的 API

java - 评论主题对象的面向对象设计

java - 我使用 ASM Toolkit 替换静态方法的主体后抛出 ClassCast 异常

java - 向 smali 源添加代码

java - 在Java中,如何检测int值设置为long变量的源

java - ASM 如何在复制操作数堆栈(DUP_X1 和 DUP 操作数)时检查最大堆栈大小