Вопрос

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

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

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

Это было полезно?

Решение

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

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

Другие советы

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

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

}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top