Java ASM, как читать значение байт-кода LOAD или STORE

Я работаю с asm (здесь документы http://asm.ow2.org/asm40/javadoc/user/), точнее, я пытаюсь динамически настроить некоторый код. Моя проблема в том, что я не знаю, как и могу ли я через то, что предлагает asm, читать фактические переменные инструментированного кода. то есть я могу получить LocalVariableNode соответствующих хранилищ, которые я вычисляю в инструментированном коде, в этот момент я хотел бы знать значение, которое я сохраняю (не только тип, который можно легко получить с помощью методов, предоставленных в классе LocalVariableNode, но фактическое значение (если это логическое значение, я хотел бы получить значение true или false)). Точно так же было бы интересно получить значение, когда происходит инструкция загрузки байт-кода.

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

Заранее спасибо. Николя


person Nicolas    schedule 26.11.2013    source источник


Ответы (2)


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

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

Каждому LocalVariableNode присваивается индекс, поэтому в байт-коде значение не связывается статически с LocalVariable, потому что Java допускает его изменение. Таким образом, чтобы узнать значение, связанное с LocalVariable в какой-то точке программы, вы должны в основном имитировать выполнение стека байт-кода (JVM), а затем иметь таблицу для отслеживания присвоения значения для каждой LocalVariable. Выполнение стека осуществляется путем имитации инструкции (кода операции), в основном байт-кода. И затем вы постепенно создаете древовидную структуру для хранения абстрактного синтаксического дерева.

У меня есть код для этого, но довольно уродливый, вы можете взглянуть: https://github.com/davidlau325/BytecodeASTGenerator

person David Lau    schedule 26.11.2013
comment
Большое спасибо, тогда попробую построить локальный стек. - person Nicolas; 26.11.2013

То, о чем вы просите, вообще невозможно. Логическое хранилище (astore, bastore, putfield, putstatic) извлекает значение из вершины стека и сохраняет его в указанном месте. Однако это значение вершины стека может быть результатом любого произвольного вычисления. Например:

boolean b = MyClass.decideWhetherProgramPHalts();

Таким образом, вы зависите от вызова метода, который может завершиться, а может и не завершиться. Ваш байт-код может выглядеть примерно так (вкратце по памяти):

invokestatic "MyClass.decideWhetherProgramPHalts()Z"
istore 1

Таким образом, значение, которое сохраняется, поступает из предыдущего invokestatic, которое может быть чем угодно, от простого return true до сетевого вызова или попытки решить проблему, о которой мы знаем, что она неразрешима.

Если вам нужен анализ, который может сказать вам true, false или I-do-not-know, вы можете попробовать платформы статического анализа, такие как WALA (http://wala.sourceforge.net). Но имейте в виду, что в большинстве случаев вы получите I-do-not-know. Вот основные методы, которые вы можете изучить:

  1. Анализ потока данных
  2. Абстрактная интерпретация

Обратите внимание, что вы, возможно, сможете провести тривиальный анализ потока данных самостоятельно, посетив инструкции в своем MethodNode, но ваш отзыв будет хуже, чем с использованием существующих инструментов (если только вы не вложите в это много работы).

person creichen    schedule 26.11.2013