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

How to detect java local variables by an interface type and then find methods called on them?

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

2015 年 9 月 1 日

为了让事情更清楚:

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

在考虑这个问题时 - 是否可以通过 ASM/javassist 检测接口中的所有可用方法并在另一个 类 中找到对它们的调用?

我不确定我是否完全理解你想要什么,但是。

您可以在每个对象上使用工具, 每个具有 getter 的对象都可以使用 class 实现它,称为 getable 。 然后你只能在具有你从 class getable 实现的功能的对象上做事。

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

恐怕,你想做的事是不可能的。在编译后的 Java 代码中,源代码中的形式没有局部变量。方法使用 stack frames ,它为局部变量保留内存,由数字索引寻址。该类型由写入它的指令暗示,并且可能会在整个方法代码中发生变化,因为内存可能会被具有分离范围的不同变量重用。另一方面,名称完全无关紧要。

验证字节码后,将对堆栈帧的所有指令的效果进行建模,以推断每个执行点的每个堆栈帧槽的类型,以便检查所有操作的有效性。从 class 文件版本 50 开始,将有 StackMapTable attributes 通过包含显式类型信息来帮助该过程,但仅适用于具有 分支 的代码。对于时序代码,变量的类型还是要通过推理推导出来。

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

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

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

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

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


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