ASM之FieldVisitor创建变量
FieldVisitor使用abstract
修饰,用于创建变量,在使用时调用 ClassWriter.visitField即可创建FieldVisitor
方法介绍
visitField(Opcodes.ACC_PUBLIC, “str”, “Ljava/lang/String;”, null, “Hello World”)
第一个参数是修饰类型,第二个参数是变量名,第三个是变量类型,第四个签名,第五个是变量的值(设置值好像没什么用,所以我在下面代码的初始化中重新初始化了str的值)
示例代码如下
package com.example.asmapplication
import org.junit.Test
import org.objectweb.asm.ClassWriter
import org.objectweb.asm.Opcodes
import java.io.File
import java.io.FileOutputStream
import java.net.URLClassLoader
class DemoASMGenerateField {
@Test
fun generate() {
val filePath =
"E:\\Develop\\ASMApplication2\\app\\src\\test\\java\\com\\example\\asmapplication\\generate\\GenerateField.class"
val file = File(filePath)
if (!file.parentFile.exists()) {
file.parentFile.mkdir()
}
//创建ClassWriter
val cw = ClassWriter(ClassWriter.COMPUTE_FRAMES)
//设定包名和类名
cw.visit(
Opcodes.V1_8,
Opcodes.ACC_PUBLIC,
"com/example/asmapplication/generate/GenerateField",
null,
"java/lang/Object",
null
)
//创建全局变量
val vfStr =
cw.visitField(Opcodes.ACC_PUBLIC, "str", "Ljava/lang/String;", null, "Hello World")
vfStr.visitEnd()
//每个classFile都有一个<init>的初始化方法
val mvInit = cw.visitMethod(Opcodes.ACC_PUBLIC, "<init>", "()V", null, null)
mvInit.visitCode()
mvInit.visitVarInsn(Opcodes.ALOAD, 0)
mvInit.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false)
mvInit.visitVarInsn(Opcodes.ALOAD, 0)
//初始化定义的变量的值
mvInit.visitLdcInsn("Hello World")
mvInit.visitFieldInsn(Opcodes.PUTFIELD, "com/example/asmapplication/generate/GenerateField", "str", "Ljava/lang/String;")
mvInit.visitInsn(Opcodes.RETURN)
mvInit.visitMaxs(0, 0)
mvInit.visitEnd()
//创建一个test()方法
val mvTest = cw.visitMethod(Opcodes.ACC_PUBLIC, "test", "()V", null, null)
mvTest.visitCode()
//打印Hello Word
mvTest.visitVarInsn(Opcodes.ALOAD, 0);
mvTest.visitFieldInsn(
Opcodes.GETFIELD,
"com/example/asmapplication/generate/GenerateField",
"str",
"Ljava/lang/String;"
);
mvTest.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;")
mvTest.visitInsn(Opcodes.SWAP)
mvTest.visitMethodInsn(
Opcodes.INVOKEVIRTUAL,
"java/io/PrintStream",
"println",
"(Ljava/lang/Object;)V",
false
)
mvTest.visitInsn(Opcodes.RETURN)
mvTest.visitMaxs(0, 0)
mvTest.visitEnd()
//类的访问结束
cw.visitEnd()
//输出为class文件
val outputStream = FileOutputStream(file)
outputStream.write(cw.toByteArray())
outputStream.flush()
outputStream.close()
val classLoader = URLClassLoader(
arrayOf(
File("E:\\Develop\\ASMApplication2\\app\\src\\test\\java").toURI().toURL()
)
)
val clazz = classLoader.loadClass("com.example.asmapplication.generate.GenerateField")
val obj = clazz.newInstance()
clazz.getMethod("test").invoke(obj)
}
}
最终生成代码:
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
package com.example.asmapplication.generate;
public class GenerateField {
public String str = "Hello World";
public GenerateField() {
}
public void test() {
System.out.println(this.str);
}
}