Как программно декомпилировать значения в исходный литерал?
Я занят простым декомпилятором для Android. Я хочу сделать хороший декомпилированный вид. Я использую dex2jar.
Допустим, у меня есть объявление поля: public byte[] test = new byte[2];
С FieldVisitor
Я получил:
public as modifier
byte[] as type
test as name
and an Object as value <--
Это возможно, если у вас есть такой объект, как byte[2]
, чтобы получить new byte[2]
literal
назад?
1 ответ
Код:
public class Foo {
public byte[] bar = new byte[3];
}
компилируется так же, как:
class Foo2 {
public byte[] bar;
public Foo2() {
this.bar = new byte[3];
}
}
Здесь нет "литерала", инициализаторы полей и блоки инициализаторов просто добавляются (я думаю, в порядке исходного кода) к коду каждого конструктора - информация, которую вы ищете, не сохраняется. Вам придется посмотреть на декомпилированный код этих конструкторов и как-то проанализировать, но это будет неоднозначно.
Операционные коды для этого конструктора:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: aload_0
5: iconst_3
6: newarray byte
8: putfield #2; //Field bar:[B
11: return
Индексы с 4 по 8 соответствуют линии this.bar = new byte[3];
, Они значат примерно:
- Нажмите
this
ссылка на стек. - Нажмите целое
3
в стек. - Pop целое число
3
) вершина стека, создайте байтовый массив такой длины, поместите массив в стек. - Установите значение, которое находится на вершине стека (байтовый массив), как значение поля #2 (это
bar
) объекта, который является вторым сверху в стеке (this
). (Кроме того, вытолкните два из стека.)
Это не очень хорошо отображает исходный код Java; как вы видите, часть, которая соответствует "new byte[3]", вставлена в середине части, которая реализует "this.bar = …", и вещи происходят не по порядку даже для такого простого выражения, как это. Реконструкция операторов из байт-кода, вероятно, не будет тривиальной - они не разграничены явно, оператор заканчивается, когда вы вытаскиваете все из стека.