我有一些(也许)奇怪的要求-我想检测给定接口名称的局部(方法)变量的定义。当找到这样的变量时,我想检测将在该变量上调用哪些方法(set / get *)。我没有运气就尝试了Javassist,现在我对ASM有了更深入的了解,但是不确定是否可以得到我想要的东西。原因是我想用GraphViz生成依赖于相同数据结构的bean的依赖关系图。如果有可能做到这一点,请有人提示我该怎么做?也许还有其他框架可以做?
2015年1月1日
为了使事情更清楚:
该界面是自行编写的-整个操作的目标是第一步自动创建依赖关系图-稍后应在基于依赖关系的图形编辑器上实现。我不知道FindBugs / PMD如何工作,因为它们还使用字节码并检测例如空指针调用(变量未初始化,将在其上调用方法)。所以我认为我可以用同样的方式来实现我的想法。整个代码都是基于Spring的-也许这可以为这个问题打开另一个解决方案?最后但并非最不重要的一点是,我可以在Source-jar上工作?
处理问题时-是否可以通过ASM / javassist从接口检测所有可用方法并在其他类中找到对它们的调用?
恐怕您想做的事是不可能的。在已编译的Java代码中,源代码中没有形式的局部变量。方法使用具有为局部变量保留的内存的堆栈帧,该内存由数字索引寻址。该类型由指令的写意所隐含,并且可能随着方法的代码在整个方法代码中发生变化,因为该内存可能会被具有相异作用域的不同变量重用。另一方面,名称是完全不相关的。
当字节码得到验证时,将对所有对堆栈帧的指令的影响进行建模,以推断在执行的每个点上每个堆栈帧插槽的类型,以便可以检查所有操作的有效性。从类文件版本开始50
,将通过包含显式类型信息(但仅适用于带有branchs的代码)来提供有助于该过程的StackMapTable
属性。对于顺序代码,变量的类型仍然必须通过推导得出。
这些推断的类型不一定是声明的类型。例如,在字节码级别上,两者之间没有区别
CharSequence cs="foo";
cs.charAt(0);
和
String s="foo";
((CharSequence)s).charAt(0);
在这两种情况下,都将String
常量存储到局部变量中,然后调用接口方法。String
在两种情况下都将使用推断的类型,并且调用CharSequence
被视为有效的String
实现的方法CharSequence
。
这与检测是否存在使用CharSequence
(interface
)类型声明的局部变量的想法相反,因为实际声明的类型无关紧要,也不存储在常规字节码中。
但是,有一些调试属性包含有关局部变量的信息,请参见该LocalVariableTable
属性,如果存在此类信息,ASM之类的库将告诉您有关声明的信息。但是您不能依赖这些可选信息。例如,Oracle的JRE库默认情况下不带它们。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句