ASM中正确使用visitLocalVariable方法的疑问及求助
ASM中正确使用visitLocalVariable方法的疑问及求助
最近我在用ASM生成Java字节码的时候,碰到了个局部变量名称乱掉的坑,研究了好一阵子没搞懂,来这儿求助各位大佬。
先说说我的操作:我想给方法里不同分支的局部变量设置不同的名称,于是写了这段ASM代码:
methodVisitor = classWriter.visitMethod(ACC_PUBLIC | ACC_STATIC, "something", "()V", null, null); methodVisitor.visitCode(); Label label0 = new Label(); methodVisitor.visitLabel(label0); methodVisitor.visitInsn(ICONST_1); Label label1 = new Label(); methodVisitor.visitJumpInsn(IFEQ, label1); methodVisitor.visitLdcInsn("number"); methodVisitor.visitVarInsn(ASTORE, 0); methodVisitor.visitVarInsn(ALOAD, 0); methodVisitor.visitMethodInsn(INVOKESTATIC, "org/bezsahara/minikotlin/NamingTests", "accept", "(Ljava/lang/Object;)V", false); methodVisitor.visitInsn(RETURN); methodVisitor.visitLabel(label1); methodVisitor.visitIntInsn(BIPUSH, 21); methodVisitor.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;", false); methodVisitor.visitVarInsn(ASTORE, 0); methodVisitor.visitVarInsn(ALOAD, 0); methodVisitor.visitMethodInsn(INVOKESTATIC, "org/bezsahara/minikotlin/NamingTests", "accept", "(Ljava/lang/Object;)V", false); methodVisitor.visitInsn(RETURN); Label label2 = new Label(); methodVisitor.visitLabel(label2); methodVisitor.visitLocalVariable("hello", "Ljava/lang/String;", null, label0, label1, 0); methodVisitor.visitLocalVariable("goodbye", "Ljava/lang/Integer;", null, label1, label2, 0); methodVisitor.visitMaxs(0, 0); methodVisitor.visitEnd();
结果用IntelliJ的FernFlower反编译后,变量名完全搞反了,和我设置的刚好相反:
public static void something() { if (true) { String goodbye = "number"; NamingTests.accept(goodbye); } else { Integer hello = 21; NamingTests.accept(hello); } }
我去对比了javac编译出来的字节码,发现好像只有LOAD操作相关的代码范围才会标记局部变量信息?这就让我很疑惑了:如果只是给变量赋值(STORE操作)的话,难道就会丢失命名信息吗?
所以想请教大家两个问题:
- 是不是只有LOAD操作对应的代码范围才需要用
visitLocalVariable来标记? - 如果是这样的设计,背后的原因是什么?为什么不能把STORE操作也包含进标记的范围里?
真心希望懂ASM或者Java字节码规范的朋友能帮忙解惑,谢谢啦!
内容来源于stack exchange
相关产品推荐
相关产品推荐

