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

时间:2011-06-04 08:11:42

标签: java static-analysis bytecode

我已经重写了这个问题(问题仍然是相同的,只是背景噪音较小),希望能够减少针对所有错误事物的混淆 - 由于这一点,下面的一些评论似乎脱离了背景。 / p>

分析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指令会收到整数的参考类型。

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 project有一个Analyzer,看起来它可能会为我做部分工作,但实际上还不足以证明转用它是合理的。

编辑:我完成了我的作业并研究了Java VM Spec

3 个答案:

答案 0 :(得分:3)

Analyzer.analyze(...)方法似乎完全符合您的需要,如果没有,您可以选择黑客入侵。这比重新开始更好。

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

答案 1 :(得分:2)

我发现需要在我的项目中做同样的事情。您可能需要查看源代码here(在visitEnd()方法中)。它使用ASM项目中的Analyzer来获取PUTFIELD指令时堆栈帧的“快照”。然后存储这些快照,并且可以在访问者完成后检索这些快照,快照中包含的部分信息是堆栈顶部的引用类型。

上面链接的特定类被设计为子类,子类的示例是here(查看visitMethod())。当我需要这样做的时候,我也转向了StackOverflow,你可能想看看the question I asked at the time,特别是链接provided in the accepted answer,它提供了我最终使用的代码的基础。

答案 2 :(得分:1)

  

我们可以推断出pc 11上的putfield指令将收到一个refger类型的整数。

您不必推断,这是putfield定义的一部分。

在编写应用程序之前,您应该花一些时间阅读VM Spec。第6节将为您提供所有字节码操作的指定行为。