Я использую asm для изменения инструкций MethodNode. Мой код строит график из methodNode.instructions. Используя этот график, я переставляю и удаляю инструкции. Затем я использую график для создания нового списка инструкций для MethodNode. Проблема в том, что в инструкциях по-прежнему есть значения для .getNext(), что приводит к добавлению в конец инструкций методов случайных инструкций, которые больше не содержатся в графе. Это также вызывает ArrayIndexOutOfBoundsException при преобразовании InsnList в массив.
Пример:
Начальные инструкции:
L0
ALOAD 1
LDC 1784196469
INVOKEVIRTUAL dq.c (I)I
ISTORE 2
ILOAD 2
IFNE L1
GOTO L2
L3
RETURN
L1
ALOAD 0
ALOAD 1
ILOAD 2
BIPUSH 15
INVOKEVIRTUAL ac.f (Ldq;IB)V
GOTO L0
L2
GOTO L3
После изменений в граф. Это инструкции, которые добавляются в methodNode.instructions после очистки списка.
L0
ALOAD 1
LDC 1784196469
INVOKEVIRTUAL dq.c (I)I
ISTORE 2
ILOAD 2
IFNE L1
RETURN
L1
ALOAD 0
ALOAD 1
ILOAD 2
BIPUSH 15
INVOKEVIRTUAL ac.f (Ldq;IB)V
GOTO L0
Когда .getNext() вызывается в последней инструкции, это результат:
org.objectweb.asm.tree.LabelNode@7a0ac6e3
Как видите, последняя добавленная инструкция (GOTO L0) имеет значение для .getNext().
Когда этот MethodNode сохраняется, а затем декомпилируется, это результат. Существует случайный оператор GOTO для несуществующей метки.
L1 {
aload1
ldc 1784196469 (java.lang.Integer)
invokevirtual dq c((I)I);
istore2
iload2
ifne L2
return
}
L2 {
aload0 // reference to self
aload1
iload2
bipush 15
invokevirtual ac f((Ldq;IB)V);
goto L1
goto L3
}
Как я могу повторно использовать инструкции из метода, если я меняю их порядок? Это ошибка или я неправильно использую asm?