Как определить размер массива в байт-коде Java (FindBugs) - PullRequest
4 голосов
/ 15 июня 2009

Я бы хотел узнать о размере выделяемого массива, посмотрев на байт-код, если, конечно, эта информация известна во время компиляции.

Справочная информация: я хочу написать детектор FindBugs (который просматривает скомпилированный байт-код) и сообщать о некоторых случаях выделения массивов. Для того, чтобы отфильтровать ложные срабатывания, меня не интересуют «маленькие» массивы, а только те, размер которых недоступен во время компиляции или которые больше настраиваемого порога.

Поскольку исходный код FindBugs не слишком документирован, я ищу несколько советов о том, как начать - возможно, уже есть дектектор, делающий нечто подобное, на что я мог бы взглянуть.

Ответы [ 2 ]

5 голосов
/ 15 июня 2009

Ну, если они распределены на основе константы, вы можете проверить постоянную, которая была передана непосредственно перед выделением. Например:

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

}
2 голосов
/ 15 июня 2009

Это может быть довольно сложно. Мои знания неполны, но у вас будет по крайней мере три вида инструкций, на которые следует обратить внимание (NEWARRAY, ANEWARRAY и MULTIANEWARRAY). Если посмотреть на предыдущую инструкцию (или в случае MULTIANEWARRAY, n предыдущие инструкции), получим размер, который, даже если он был константой, может быть загружен с помощью BIPUSH, SIPUSH или LDC (что-нибудь еще?) В зависимости от размер. Как вы заметили, если класс является результатом вычислений, вы можете прослеживать инструкции до бесконечности.

Если я правильно помню, FindBugs использует BCEL внутри, но я никогда не копался там, чтобы точно понять, насколько они умны. Если у какой-либо из этих групп есть соответствующие списки рассылки, они могут оказаться лучшим местом, чтобы спросить - они, вероятно, по крайней мере узнают, был ли кто-то по этому пути раньше.

...