问题描述
使用org.objectweb.asm库的Kotlin代码
import org.objectweb.asm.ClassWriter
import org.objectweb.asm.Opcodes.*
fun main(args: Array<String>) {
val classWriter = ClassWriter(ClassWriter.COmpuTE_MAXS)
classWriter.visit(
V1_8,ACC_PUBLIC,"com/github/patrick/learnasm/build/HelloWorld",null,"java/lang/Object",null
)
val methodVisitor = classWriter.visitMethod(
ACC_PUBLIC + ACC_STATIC,"main","([Ljava/lang/String;)V",null
)
methodVisitor.visitFieldInsn(
GETSTATIC,"java/lang/System","out","Ljava/io/PrintStream;"
)
methodVisitor.visitLdcInsn(
"Hello World!"
)
methodVisitor.visitMethodInsn(
INVOKEVIRTUAL,"java/io/PrintStream","println","(Ljava/lang/String;)V",false
)
methodVisitor.visitInsn(
RETURN
)
methodVisitor.visitMaxs(
0,0
)
methodVisitor.visitEnd()
val bytes = classWriter.toByteArray()
val clazz = defineClass(
"com.github.patrick.learnasm.build.HelloWorld",bytes,bytes.count()
)
clazz.getDeclaredMethod("main",Array<String>::class.java).invoke(null,null)
}
我正在尝试学习asm,并且很好奇是否可以创建带有命名参数的方法。
例如,在这种情况下,创建的类没有参数名称(在反编译器中默认为var0),我希望我可以保存“ args”之类的参数名称。有可能吗?
解决方法
通过查看已编译的类(包括调试信息)来找到答案
简单的方法是仅模拟编译的类
我要做的就是在上面贴上标签,并访问带有名称的局部变量。
methodVisitor = classWriter.visitMethod(
Opcodes.ACC_PUBLIC + Opcodes.ACC_STATIC,"main","([Ljava/lang/String;)V",null,null
)
methodVisitor.visitParameterAnnotation(
0,"Lorg.jetbrains.annotations.NotNull;",false
)
val start = Label()
methodVisitor.visitLabel(start)
methodVisitor.visitFieldInsn(
Opcodes.GETSTATIC,"java/lang/System","out","Ljava/io/PrintStream;"
)
methodVisitor.visitLdcInsn("Hello World!")
methodVisitor.visitMethodInsn(
Opcodes.INVOKEVIRTUAL,"java/io/PrintStream","println","(Ljava/lang/String;)V",false
)
methodVisitor.visitInsn(Opcodes.RETURN)
val end = Label()
methodVisitor.visitLabel(end)
methodVisitor.visitLocalVariable(
"args","[Ljava/lang/String;",start,end,0
)
methodVisitor.visitMaxs(0,0)
methodVisitor.visitEnd()