2009-06-15 69 views
4

我想通過查看字節碼來了解正在分配的數組的大小,當然,如果在編譯時知道該信息。背景:我想編寫一個FindBugs檢測器(它查看編譯的字節碼)並報告某些數組分配的事件。爲了濾除誤報,我對「小」數組不感興趣,但只有那些在編譯時不可用或者大於可配置閾值的數組。由於FindBugs源代碼沒有過多的文檔記錄,我正在尋找一些關於如何開始的指針 - 也許已經有一個檢測器做了類似的事情,我可以看看。如何檢測Java字節碼中的數組大小(FindBugs)

回答

2

這可以得到一定的技巧。我的知識不完整,但至少有三種指示要注意(NEWARRAY,ANEWARRAY和MULTIANEWARRAY)。查看前面的指令(或者對於MULTIANEWARRAY,n先前的指令)會獲得大小,即使它是常量,也可能會根據大小加載BIPUSH,SIPUSH或LDC(其他任何東西?)。正如你所指出的,如果這個類是計算的結果,你可能會無限期地追蹤指令。

如果我沒有記錯的話,FindBugs會在內部使用BCEL,但我從來沒有在那裏挖過來看到他們究竟有多聰明。如果其中任何一支隊伍都有適當的郵件列表,他們可能會證明是一個更好的地方 - 他們可能至少知道是否有人在此之前走過這條路。

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 

} 
+0

謝謝,這已經是一個開始。在你的例子中,它會內聯常量。當你有像 int x = 10; 新字節[5 + x]; 雖然15是明顯的結果,但取決於編譯器(及其設置),這可能最終會在新分配之前在堆棧上進行計算。我想知道,如果在FindBugs中有一個標準的方法來實現這個功能。 – 2009-06-15 13:51:56