如何静态分析传递给每个字节码指令的引用类型?

2022-09-04 04:26:17

我已经重写了这个问题(问题保持不变,只是背景噪音更少),希望减少针对所有错误事物的混乱 - 因此,下面的一些评论可能看起来脱离了上下文。

分析 Java 字节码,找到给定 Java 字节码指令的参数给出的所有可能的引用类型的最简单方法是什么?我对引用的类型感兴趣,也就是说,给定的 putfield 指令将接收 Integer,或者它可能会接收 Integer 或 Float 等。

例如,请考虑以下代码块:

   0:   aload_1
   1:   invokestatic    #21; //Method java/lang/Integer.valueOf:(Ljava/lang/String;)Ljava/lang/Integer;
   4:   astore_2
   5:   aload_2
   6:   ifnull  17
   9:   aload_0
   10:  aload_2
   11:  putfield    #27; //Field value:Ljava/lang/Number;
   14:  goto    25
   17:  aload_0
   18:  iconst_0
   19:  invokestatic    #29; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
   22:  putfield    #27; //Field value:Ljava/lang/Number;
   25:  return

我们可以推断出 pc 11 中的 putfield 指令将收到一个 ref 类型的 Integer

0: aload pushes ref type of String (the method param)
1: invokestatic pops the ref type and pushes a ref type of Integer (invoked method return type)
4: astore pops the ref type of Integer and stores it in local variable 2
5: aload pushes the ref type of Integer from local variable 2
6: ifnull pops the ref type of Integer and conditionally jumps to pc 17
9: aload pushes "this"
10: aload pushes the ref type of Integer
11: putfield: we know we have a ref type of Integer that the instruction will put in field

是否有任何字节码/代码分析库为我执行此操作,或者我必须自己编写此内容?ASM项目有一个分析器,它似乎可以为我完成部分工作,但实际上不足以证明切换到使用它是合理的。

编辑:我已经完成了我的功课,并研究了Java VM规范


答案 1

Analyzer.analyze(...)方法似乎完全符合您的需要,如果没有,您可以选择对其进行黑客攻击。这将是一个比重新开始更好的方法。

另一个想法是看看你是否能找到一个用Java实现的字节码验证器。验证程序必须使用数据流分析来确保不会使用错误类型的参数调用方法。


答案 2

我发现需要在我的一个项目上做几乎完全相同的事情。您可能希望在此处(在方法中)查看源代码。它使用来自 ASM 项目的在指令时拍摄堆栈帧的“快照”。然后存储这些快照,并且可以在访问者完成后检索,快照中包含的部分信息是堆栈顶部的引用类型。visitEnd()AnalyzerPUTFIELD

链接到上面的特定类被设计为子类,子类的示例在这里(查看)。在我需要这样做的时候,我也转向了StackOverflow,你可能想看看我当时提出的问题,特别是接受的答案中提供的链接,它提供了我最终使用的代码的基础。visitMethod()


推荐