我正在使用asm来修改MethodNode的指令。我的代码从methodNode.instructions构造一个图。使用此图表,我重新排列并删除指令。然后,我使用该图生成MethodNode的新指令列表。问题是指令仍然具有.getNext()的值,这会导致图形中不再包含的杂散指令被添加到方法指令的末尾。将InsnList转换为数组时,这也会导致ArrayIndexOutOfBoundsException。
示例:
初步说明:
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
图表更改后。这些是清除列表后添加到methodNode.instructions的指令。
org.objectweb.asm.tree.LabelNode@7a0ac6e3
当在最后一条指令上调用.getNext()时,结果如下:
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
}
如您所见,添加的最后一条指令(GOTO L0)的值为.getNext()
保存此MethodNode然后反编译时,结果就是这样。对于不存在的标签,存在一个迷失的GOTO语句。
[Tue, 05 Apr 2016 21:45:25 GMT] INFO: [ARENA] The boss was defeated by 'madmikegamerxl1'. The boss health is: -30
[Tue, 05 Apr 2016 21:45:25 GMT] INFO: Game was won, looping to add XP and restore users. Current user: ethelwolv
[Tue, 05 Apr 2016 21:45:25 GMT] INFO: Finished updating user 0/8(ethelwolv)
[Tue, 05 Apr 2016 21:45:25 GMT] INFO: Game was won, looping to add XP and restore users. Current user: shauncox12345
[Tue, 05 Apr 2016 21:45:25 GMT] INFO: Finished updating user 1/8(shauncox12345)
[Tue, 05 Apr 2016 21:45:25 GMT] INFO: Game was won, looping to add XP and restore users. Current user: orpheussummanus
[Tue, 05 Apr 2016 21:45:25 GMT] INFO: Finished updating user 2/8(orpheussummanus)
[Tue, 05 Apr 2016 21:45:25 GMT] INFO: Game was won, looping to add XP and restore users. Current user: acermekz21
[Tue, 05 Apr 2016 21:45:25 GMT] INFO: Finished updating user 3/8(acermekz21)
[Tue, 05 Apr 2016 21:45:25 GMT] INFO: Game was won, looping to add XP and restore users. Current user: sturgisdanielle
[Tue, 05 Apr 2016 21:45:25 GMT] INFO: Finished updating user 4/8(sturgisdanielle)
[Tue, 05 Apr 2016 21:45:25 GMT] INFO: Game was won, looping to add XP and restore users. Current user: minnie2292
[Tue, 05 Apr 2016 21:45:25 GMT] INFO: Finished updating user 5/8(minnie2292)
[Tue, 05 Apr 2016 21:45:25 GMT] INFO: Game was won, looping to add XP and restore users. Current user: epicminer4354
[Tue, 05 Apr 2016 21:45:25 GMT] INFO: Finished updating user 6/8(epicminer4354)
[Tue, 05 Apr 2016 21:45:25 GMT] INFO: Game was won, looping to add XP and restore users. Current user: madmikegamerxl1
[Tue, 05 Apr 2016 21:45:25 GMT] INFO: Finished updating user 7/8(madmikegamerxl1)
[Tue, 05 Apr 2016 21:45:26 GMT] INFO: User 'x0slipknot0x' was not defeated by the boss, incrementing win count
[Tue, 05 Apr 2016 21:45:28 GMT] INFO: User 'madmikegamerxl1' was not defeated by the boss, incrementing win count
[Tue, 05 Apr 2016 21:45:28 GMT] INFO: User 'madmikegamerxl1' was not defeated by the boss, incrementing win count
[Tue, 05 Apr 2016 21:45:28 GMT] INFO: User 'madmikegamerxl1' was not defeated by the boss, incrementing win count
[Tue, 05 Apr 2016 21:45:28 GMT] INFO: User 'madmikegamerxl1' was not defeated by the boss, incrementing win count
[Tue, 05 Apr 2016 21:45:28 GMT] INFO: User 'madmikegamerxl1' was not defeated by the boss, incrementing win count
[Tue, 05 Apr 2016 21:45:28 GMT] INFO: User 'madmikegamerxl1' was not defeated by the boss, incrementing win count
[Tue, 05 Apr 2016 21:45:28 GMT] INFO: User 'madmikegamerxl1' was not defeated by the boss, incrementing win count
[Tue, 05 Apr 2016 21:45:28 GMT] INFO: User 'madmikegamerxl1' was not defeated by the boss, incrementing win count
如果我改变它们的顺序,我该如何重用该方法的指令?这是一个错误还是我使用asm错误?
答案 0 :(得分:1)
InsnList
是AbstractInsnNode
的链接列表。 AbstractInsnNode
的每个实例都有一个名为next
的指针,指向列表中的下一个节点。
重新排列列表中的节点时,您还需要处理这些指针。在您的情况下,GOTO L0
的节点最初指向L2
,并且由于其next
指针在重新排列期间尚未更新,因此它仍会在结尾处指向L2
。
似乎没有简单的解决方案来更新next
指针。它没有setter方法。 clear
方法没有这样做。 removeAll
方法不可见。
一些可能性可能是(i)在重用之前使用remove
从列表中删除所有节点;或(ii)为新清单构建新节点。