使用 asm 生成字节码
Generating bytecode using asm
我有这样的代码:
tracker.setValue(false);
为此我需要通过 ASM 生成字节码。所以使用该工具,我发现上面一行的字节码指令是:
ALOAD 0
GETFIELD example/MethodAdapter.tracker : Lexample/Tracker;
ICONST_0
INVOKEVIRTUAL example/Tracker.setValue (Z)V
所以当我将其转换为 ASM 代码时,它看起来像这样:
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, "example/MethodAdapter", "tracker", "Lexample/Tracker;");
mv.visitInsn(ICONST_0);
mv.visitMethodInsn(INVOKEVIRTUAL, "example/Tracker", "setValue", "(Z)V", false);
(此代码片段被写入 visitMethodInsn
)但是 运行 上面的带有 -javaagent
的 ASM 用于测试 class ,我得到一个异常说:
Exception Details:
Location:
TestClass.main([Ljava/lang/String;)V @20: getfield
Reason:
Type '[Ljava/lang/String;' (current frame, stack[0]) is not assignable to 'example/MethodAdapter'
Current Frame:
bci: @20
flags: { }
locals: { '[Ljava/lang/String;', 'TestClass' }
stack: { '[Ljava/lang/String;' }
Bytecode:
0000000: b800 02bb 0003 59b7 0004 4c2b b600 052b
0000010: b600 062a b400 2a03 b600 30b8 0007 b1
at java.lang.Class.getDeclaredMethods0(Native Method)
at java.lang.Class.privateGetDeclaredMethods(Class.java:2688)
at java.lang.Class.getMethod0(Class.java:2937)
at java.lang.Class.getMethod(Class.java:1771)
at sun.launcher.LauncherHelper.validateMainClass(Unknown Source)
at sun.launcher.LauncherHelper.checkAndLoadMain(Unknown Source)
我发现问题出在这一行:
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, "example/MethodAdapter", "tracker", "Lexample/Tracker;");
看起来 0
的 ALOAD
没有提取正确的 this
或者我在这里遗漏了什么?
您正在将代码插入 main
函数,该函数是静态的,因此没有 this
参数。第一个参数是字符串数组。
我有这样的代码:
tracker.setValue(false);
为此我需要通过 ASM 生成字节码。所以使用该工具,我发现上面一行的字节码指令是:
ALOAD 0
GETFIELD example/MethodAdapter.tracker : Lexample/Tracker;
ICONST_0
INVOKEVIRTUAL example/Tracker.setValue (Z)V
所以当我将其转换为 ASM 代码时,它看起来像这样:
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, "example/MethodAdapter", "tracker", "Lexample/Tracker;");
mv.visitInsn(ICONST_0);
mv.visitMethodInsn(INVOKEVIRTUAL, "example/Tracker", "setValue", "(Z)V", false);
(此代码片段被写入 visitMethodInsn
)但是 运行 上面的带有 -javaagent
的 ASM 用于测试 class ,我得到一个异常说:
Exception Details:
Location:
TestClass.main([Ljava/lang/String;)V @20: getfield
Reason:
Type '[Ljava/lang/String;' (current frame, stack[0]) is not assignable to 'example/MethodAdapter'
Current Frame:
bci: @20
flags: { }
locals: { '[Ljava/lang/String;', 'TestClass' }
stack: { '[Ljava/lang/String;' }
Bytecode:
0000000: b800 02bb 0003 59b7 0004 4c2b b600 052b
0000010: b600 062a b400 2a03 b600 30b8 0007 b1
at java.lang.Class.getDeclaredMethods0(Native Method)
at java.lang.Class.privateGetDeclaredMethods(Class.java:2688)
at java.lang.Class.getMethod0(Class.java:2937)
at java.lang.Class.getMethod(Class.java:1771)
at sun.launcher.LauncherHelper.validateMainClass(Unknown Source)
at sun.launcher.LauncherHelper.checkAndLoadMain(Unknown Source)
我发现问题出在这一行:
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, "example/MethodAdapter", "tracker", "Lexample/Tracker;");
看起来 0
的 ALOAD
没有提取正确的 this
或者我在这里遗漏了什么?
您正在将代码插入 main
函数,该函数是静态的,因此没有 this
参数。第一个参数是字符串数组。