Как статически анализировать ссылочные типы, переданные каждой инструкции байткода?

Я переписал вопрос (вопрос остается тем же, только с меньшим фоновым шумом) в надежде создать меньшую путаницу, направленную на все неправильные вещи - из-за этого некоторые из комментариев ниже могут показаться вне контекста.

Анализируя байт-код 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

Мы можем вывести, что команда putfield в pc 11 получит тип ref Integer.

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 имеет Analyzer, который кажется он может сделать часть работы для меня, но на самом деле недостаточно, чтобы оправдать переход на ее использование.

EDIT: Я сделал домашнее задание и изучил Java VM Spec.

Ответы

Ответ 1

Метод Analyzer.analyze(...), похоже, делает именно то, что вам нужно, и, если нет, у вас есть возможность взломать его. Это было бы лучше, чем начинать заново.

Еще одна идея - посмотреть, можно ли найти верификатор байт-кода, реализованный на Java. Верификатор должен использовать анализ потока данных, чтобы гарантировать, что методы не вызываются с неправильным типом параметров.

Ответ 2

Я нашел необходимость делать практически то же самое в моем проекте. Вы можете взглянуть на исходный код здесь (в методе visitEnd()). Он использует Analyzer из проекта ASM для получения "моментального снимка" кадра стека во время инструкции PUTFIELD. Эти снимки затем сохраняются и могут быть восстановлены после завершения посетителя, часть информации, содержащейся в снимке, является типом ссылки в верхней части стека.

Конкретный класс, связанный с выше, предназначен для подкласса, пример подкласса здесь (проверьте visitMethod()). В то время, когда мне нужно было это сделать, я тоже обратился к StackOverflow, вы можете проверить вопрос, который я задал в то время, в частности ссылку представленный в принятом ответе, который послужил основой для кода, который я в конечном итоге использовал.

Ответ 3

Мы можем вывести, что команда putfield на pc 11 получит тип ref Integer.

Вам не нужно выводить это, это часть определения putfield.

Прежде чем писать приложение, вы должны потратить некоторое время на чтение VM Spec. Раздел 6 предоставит вам определенное поведение всех операций байт-кода.