问题如下;
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(),然后看看有什么参数并正确检测……
但我没有任何想法从哪里开始;在网上搜索似乎只是举例说明如何修改字节码,而不是检测这种情况:/
我从哪里开始?