Java ASM, как прочитать значение байт-кода LOAD или STORE
Я работаю с asm (здесь документы http://asm.ow2.org/asm40/javadoc/user/), более конкретно, я пытаюсь динамически инструментировать некоторый код. Моя проблема в том, что я не знаю, как и если я могу через то, что предлагает asm, чтобы прочитать фактические переменные инструментального кода. т.е. я могу извлечь LocalVariableNode из соответствующих хранилищ, которые я вычисляю в инструментальном коде, на данный момент я хотел бы знать значение, которое я храню (не только тип, который можно легко получить с помощью методов, предоставленных в классе LocalVariableNode, но фактическое значение (если это логическое значение, я хотел бы получить значение true или false)). Точно так же было бы интересно получить значение, когда происходит инструкция загрузки байт-кода.
Надеюсь, я был достаточно конкретен, я проверил, если что-то подобное уже спрашивали, но, похоже, это не так
Заранее спасибо. никола
2 ответа
Некоторое время назад я делал нечто похожее, забыв про детали, но думаю, что могу дать вам несколько советов по этому поводу.
Конечно, как сказал Крейчен в своем ответе, невозможно получить точное значение, связанное с LocalVariable, но можно как-то получить полное дерево абстрактного синтаксиса байт-кода и узнать, какое возможное значение будет присвоено этому. LocalVariable в какой-то момент программы.
Для каждого LocalVariableNode присваивается индекс, поэтому в байт-коде значение не является статически связанным с LocalVariable, потому что Java допускает изменчивость на этом. Таким образом, чтобы узнать значение, связанное с LocalVariable в некоторой точке программы, вы должны в основном смоделировать выполнение стека байт-кода (JVM), а затем иметь таблицу для отслеживания назначения значения для каждой LocalVariable. Выполнение стека осуществляется посредством имитации инструкции (кода операции), в основном байт-кода. И затем вы постепенно строите древовидную структуру для хранения абстрактного синтаксического дерева.
У меня есть код для этого, но довольно уродливо, вы можете посмотреть: https://github.com/davidlau325/BytecodeASTGenerator
То, что вы просите, вообще невозможно. Булевый магазин (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
, Вот основные приемы, которые вы можете рассмотреть:
- Анализ потока данных
- Абстрактная интерпретация
Обратите внимание, что вы можете самостоятельно приступить к анализу тривиального потока данных, посетив инструкции в вашем MethodNode, но ваш отзыв будет хуже, чем использование существующих инструментов (если вы не потратите на это много работы).