我正在尝试将AST编译成一个java类文件,使用ASM来创建类本身。当我试图向函数添加局部变量(函数是正确创建的)时,我遇到了一个问题。
一个像这样简单的函数:
public void test() {
int a = 10;
int b = 11;
int c = 12;
int d = 1;
}一旦被插装(用JD解压缩),就会变成这样:
public void test() {
int i = 10;
int j = 11;
int k = 12;
int m = 4;
}它的字节码如下所示:
public test() { //()V
bipush 10
istore1
bipush 11
istore2
bipush 12
istore3
iconst_4
istore4
return
}我正在创建这样的局部变量:
methodVisitor.visitVarInsn(Opcodes.BIPUSH, symbol.value);
methodVisitor.visitVarInsn(Opcodes.ISTORE, position);symbol是当前局部变量,position是基于1的索引.F.e.a将位于1位置,d将位于4位置。
我的问题是对不同的值正确地使用Opcodes。我尝试了类似于Opcodes的Opcodes.LDC,但是生成的类在其方法中没有任何局部变量,但是所有全局定义的变量和函数都在其中两次。
向方法中添加任意类型和任意值变量的正确方法是什么?
编辑:
根据评论,我试图将其他问题的答案合并如下:
MethodVisitor methodVisitor = cw.visitMethod(
access,
methodName,
typeDescriptors,
null,
null
);
LocalVariablesSorter mv = new LocalVariablesSorter(access, typeDescriptors, methodVisitor);然后使用LocalVariablesSorter添加一个局部变量,如下所示:
// type is net.bytebuddy.jar.asm.Type.INT_TYPE
net.bytebuddy.jar.asm.Type type = getType(symbol.type);
int id = mv.newLocal(type);
mv.visitVarInsn(Opcodes.ISTORE, id);其中分解为:
/* Error */
public void test()
{
// Byte code:
// 0: istore_2
// 1: istore 4
// 3: istore 6
// 5: istore 8
// 7: return
}导致这一字节码:
public test() { //()V
istore2
istore4
istore6
istore8
return
}我在这里错过了什么?
发布于 2017-06-21 16:52:00
ISTORE指令将堆栈顶部的值存储到寄存器中。堆栈上没有值,这将导致验证错误。
例如,如果要存储值2,首先需要将值加载到堆栈中:
net.bytebuddy.jar.asm.Type type = getType(symbol.type);
int id = mv.newLocal(type);
mv.visitInsn(Opcodes.ICONST_2);
mv.visitVarInsn(Opcodes.ISTORE, id);对于“更高”的值,还有其他指令,如BIPUSH或SIPUSH。否则,可以使用LDC从常量池加载值。这通常是存储值的最有效的方式;ASM隐式地重复其中的值。
https://stackoverflow.com/questions/44676210
复制相似问题