fge*_*fge 5 java bytecode java-bytecode-asm
问题如下; Java代码中的方法是:
Rule foo()
{
return sequence(foo(), x());
}
Run Code Online (Sandbox Code Playgroud)
这将引发解析循环,当然应该避免; 但是,这是合法的:
Rule foo()
{
return sequence(x(), foo());
}
Run Code Online (Sandbox Code Playgroud)
现在,代码中的其他地方我可以访问a 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
Run Code Online (Sandbox Code Playgroud)
这意味着我必须提供给我的每一个信息,能够发现,至少在上面的字节码,这foo()是第一个参数的的sequence()调用,因为构造函数接受三个参数,并有在堆栈上三个要素.
但当然我不能在运行时"眼睛检查".因此我需要一种方法来做到这一点......
看起来我需要的是a MethodVisitor和some visitInsn(),然后看看有什么参数并适当检测......
但我没有任何想法从哪里开始; 在网上搜索似乎只是举例说明如何修改字节码,而不是检测这种情况:/
我从哪里开始?
创建一个,当您在该方法的访问代码()MethodVistor中时,查找访问方法Insn(),如果其中的参数是,则您知道对该方法进行了递归调用。foo()namevisitMethodInsn()foo
在字节码列表中,您有三个INVOKEVIRTUAL指令,函数按顺序访问这些指令visitMethodInsn()。如果您想检查顺序,您可以跟踪方法调用的顺序。您将看到foo()第一个,x()然后是最后sequence()。
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;
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
478 次 |
| 最近记录: |