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

标签 java bytecode analysis javassist

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

2015年9月1日

为了让事情更清楚:

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

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

最佳答案

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

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

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

CharSequence cs="foo";
cs.charAt(0);

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

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

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

<小时/>

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

关于java - 如何通过接口(interface)类型检测java局部变量,然后找到调用它们的方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32311973/

相关文章:

java - Ubuntu:OpenJDK 8 - 无法找到包

java - 如何制作 32 位或 64 位应用程序?

java - 这段代码中的增长函数和阶数是什么?

java - 当我尝试在 java 中调用该类时,为什么我会得到一个空白表单

java - 如何使用 VisualVM 获取方法的总时间

java - Flux.onErrorContinue 参数类型

android - dalvik 上的字节码注入(inject)

Java类反编译和重新编译

用于分析眼动追踪数据的 R 包

speech-recognition - 音频分析以检测人声、性别、年龄和情绪——之前做过任何开源工作吗?