ASM - strange localVar index using newLocal from LocalVariableSorter

徘徊边缘 提交于 2020-01-04 09:22:43

问题


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'm adding two locals; one long, one object. There are no other local vars in the sample code.

As a result I would have expected the following slots / indexes:

0 - this
1 - the long param
3 - my 1st local added via `newLocal` - using two slots as it is a long
5 - my 2nd local added via `newLocal`

What I do get as return from newLocal is 3 and 7 though. Why such a big gap?

And to make things even more strange, when I add xSTORE instructions using those indexes and check the result with javap it shows me:

LSTORE 5
ASTORE 8

Note: Not only are the values different then the ones I've passed to the xSTORE instruction, also the gap between them is now 3 instead of 4 as before.

The resulting code works though. I would just like to understand what magic is happening here an why.

Thanks


回答1:


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.



来源:https://stackoverflow.com/questions/50140365/asm-strange-localvar-index-using-newlocal-from-localvariablesorter

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!