4

我想通过查看字节码来了解分配的数组的大小,当然,如果该信息在编译时是已知的。

背景:我想编写一个 FindBugs 检测器(它查看已编译的字节码)并报告某些数组分配的发生。为了过滤掉误报,我对“小”数组不感兴趣,而只对那些大小在编译时不可用或大于可配置阈值的数组感兴趣。

由于 FindBugs 源代码没有太多的文档记录,我正在寻找一些关于如何开始的指示——也许已经有一个检测器在做类似的事情,我可以看看。

4

2 回答 2

5

好吧,如果它们是基于常量分配的,您可以检查在分配之前推送的常量。例如:

class ArraySize {
    private static final int smallsize = 10;
    private static final int largesize = 1000;
    public static void main(String[] args) {
        int[] small = new int[smallsize];
        int[] big = new int[largesize];
    }
}

给出字节码:

Compiled from "ArraySize.java"
class ArraySize extends java.lang.Object{
ArraySize();
  Code:
   0:   aload_0
   1:   invokespecial   #1; //Method java/lang/Object."<init>":()V
   4:   return

public static void main(java.lang.String[]);
  Code:
   0:   bipush  10
   2:   newarray int
   4:   astore_1
   5:   sipush  1000
   8:   newarray int
   10:  astore_2
   11:  return

}
于 2009-06-15T13:31:12.563 回答
2

这可能会有点棘手。我的知识不完整,但您至少需要注意三种指令(NEWARRAY、ANEWARRAY 和 MULTINEWARRAY)。查看前面的指令(或者在 MULTIANEWARRAY 的情况下,n前面的指令)得到大小,即使它是一个常量,也可能根据大小加载 BIPUSH、SIPUSH 或 LDC(其他什么?)。正如您所指出的,如果该类是计算的结果,您可能会无限期地追溯指令。

如果我没记错的话,FindBugs 在内部使用了 BCEL,但我从来没有在那里挖掘过它们究竟有多聪明。如果这些团队中的任何一个有适当的邮件列表,他们可能会证明是一个更好的地方问 - 他们可能至少会知道是否有人曾经走过这条路。

于 2009-06-15T14:28:38.413 回答