ASM - strange localVar index using newLocal from LocalVariableSorter

后端 未结 1 998
感情败类
感情败类 2021-01-14 07:37

I\'m adding new locals via newLocal from LocalVariableSorter. The method I\'m adding the locals to is an instance method with a long parameter. I\'

相关标签:
1条回答
  • 2021-01-14 08:22

    The LocalVariableSorter class has a design, which makes it very easy to use it wrong.

    When calling methods defined by the MethodVisitor API on it, they undergo the renumbering mentioned in the class documentation.
    So when being used with a ClassReader, the visited old code gets transformed. Since you do not want the injected new code to undergo this transformation, but to use the newly defined variable(s), you have to bypass the LocalVariableSorter and call methods on the underlying target MethodVisitor.

    When you call visitVarInsn(LSTORE, 3) on the LocalVariableSorter, it gets handled like an old instruction referring to index 3 and since you injected a new variable occupying index 3 and 4, the “old variable” at index 3 gets remapped to the next free index, which is 5 (and 6). Then, when you define your next new variable, it gets index 7 and calling visitVarInsn(ASTORE, 7) on the LocalVariableSorter is handled like an old variable which conflicts with your new variable, so it gets remapped to 8.

    This behavior matches exactly what the first sentence of the class documentation states:

    LocalVariablesSorter

    A MethodVisitor that renumbers local variables in their order of appearance.

    So while you have to call newLocal on the LocalVariableSorter to create a new variable that won’t get remapped, you have to call the visit… methods on the original, wrapped MethodVisitor to use it. When you use the subclass GeneratorAdapter, you can use its newly defined methods (those not starting with visit…) to create new instructions which don’t get transformed, but to me, this would make matters even worse, having methods for transforming instructions and creating untransformed instructions on the same class and always needing to keep in mind that the visit… prefix makes the difference. For some methods, you would still need to access the original method visitor, as discussed in this answer which deals with visitLocalVariable to create debug information for the created variable.

    0 讨论(0)
提交回复
热议问题