如何通过接口类型检测java局部变量,然后找到调用它们的方法?

时间:2015-08-31 13:04:18

标签: java bytecode analysis javassist

我有一些(可能)奇怪的要求 - 我想检测给定接口名称的本地(方法)变量的定义。当找到这样一个变量时,我想检测在这个变量上调用哪些方法(set / get *)。 我没有运气就试过Javassist,现在我对ASM有了更深入的了解,但不确定它是否可能是我想要的。 这样做的原因是我喜欢使用依赖于相同数据结构的Bean的GraphViz生成依赖图。 如果有可能,有人可以给我一个如何做到的提示吗?也许还有其他框架可以做到吗?

2015年9月1日

为了使事情更清楚:

接口是自编写的 - 整个操作的目标是在第一步中自动创建依赖关系图 - 稍后应该实现基于依赖关系的图形编辑器。 我想知道FindBugs / PMD是如何工作的,因为它们也使用字节代码并检测例如空指针调用(变量未初始化并且将在其上调用方法)。所以我认为我可以用同样的方式实现我的想法。整个代码是基于Spring的 - 也许这会打开另一个解决方案?最后但并非最不重要的是,我可以在Source-jar上工作?

关于问题的问题 - 是否可以通过ASM / javassist从接口检测所有可用的方法并在其他类中查找对它们的调用?

2 个答案:

答案 0 :(得分:1)

我害怕,你想做的事是不可能的。在编译的Java代码中,源代码中的表单中没有局部变量。方法使用具有为局部变量保留的内存的stack frames,其由数字索引寻址。该类型由写入其中的指令隐含,并且可能在整个方法的代码中发生变化,因为内存可能会被重用于具有析取范围的不同变量。另一方面,这些名字完全无关紧要。

当字节码被验证时,所有指令对堆栈帧的影响将被建模以推断每个执行点处的每个堆栈帧槽的类型,以便可以检查所有操作的有效性。从类文件版本50开始,将StackMapTable attributes通过包含显式类型信息来帮助该过程,但仅适用于具有分支的代码。对于顺序代码,变量的类型仍然必须通过推理得出。

这些推断类型不一定是声明的类型。例如,在字节码级别上,

之间没有区别
CharSequence cs="foo";
cs.charAt(0);

String s="foo";
((CharSequence)s).charAt(0);

在这两种情况下,都会将String常量存储到局部变量中,然后调用接口方法。在两种情况下,推断类型都为String,并且CharSequence方法的调用被视为有效String实现CharSequence

这反驳了检测是否存在使用CharSequenceinterface)类型声明的局部变量的想法,因为实际声明的类型是无关紧要的并且不存储在常规字节代码中。

但是,调试属性包含有关局部变量的信息,如果存在此类信息,请参阅LocalVariableTable attribute和ASM will tell you about the declarations等库。但是你不能依赖这些可选信息。例如。默认情况下,Oracle的JRE库没有它们。

答案 1 :(得分:-3)

我不确定我是什么意思,但是。

你可以在每个对象上使用工具, 具有getter的evry对象可以使用名为getable的类来实现它。 然后你只能在具有你从getable类实现的函数的对象上做东西。

https://docs.oracle.com/javase/tutorial/java/IandI/createinterface.html