使用asm重建方法时的杂散指令

时间:2016-04-05 22:29:09

标签: java bytecode java-bytecode-asm

我正在使用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错误?

1 个答案:

答案 0 :(得分:1)

InsnListAbstractInsnNode的链接列表。 AbstractInsnNode的每个实例都有一个名为next的指针,指向列表中的下一个节点。

重新排列列表中的节点时,您还需要处理这些指针。在您的情况下,GOTO L0的节点最初指向L2,并且由于其next指针在重新排列期间尚未更新,因此它仍会在结尾处指向L2

似乎没有简单的解决方案来更新next指针。它没有setter方法。 clear方法没有这样做。 removeAll方法不可见。

一些可能性可能是(i)在重用之前使用remove从列表中删除所有节点;或(ii)为新清单构建新节点。