ASM之MethodWriter创建方法并支持传参
这里我们除了创建了一个方法,并且在里面加入了函数参数和max计算传入参数谁更大的代码
代码如下:
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 ASMGenerateArgMethod {
@Test
fun generate(){
val filePath = "E:\\Develop\\ASMApplication2\\app\\src\\test\\java\\com\\example\\asmapplication\\generate\\GenerateArgMethod.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/GenerateArgMethod",null,"java/lang/Object",null)
//每个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.visitInsn(Opcodes.RETURN)
mvInit.visitMaxs(1, 1);
mvInit.visitEnd()
//创建一个test()方法
val mvTest = cw.visitMethod(Opcodes.ACC_PUBLIC,"test","(II)V",null,null)
mvTest.visitCode()
mvTest.visitVarInsn(Opcodes.ILOAD, 1)
mvTest.visitVarInsn(Opcodes.ILOAD, 2)
mvTest.visitMethodInsn(Opcodes.INVOKESTATIC,"java/lang/Math", "max", "(II)I", false)
mvTest.visitVarInsn(Opcodes.ISTORE,3)
mvTest.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;")
mvTest.visitVarInsn(Opcodes.ILOAD,3)
mvTest.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/io/PrintStream", "println", "(I)V", false)
mvTest.visitInsn(Opcodes.RETURN)
mvTest.visitMaxs(2, 1)
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.GenerateArgMethod")
val obj = clazz.newInstance()
clazz.getMethod("test",Int::class.java,Int::class.java).invoke(obj,1,2)
}
}
生成的代码如下
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
package com.example.asmapplication.generate;
public class GenerateArgMethod {
public GenerateArgMethod() {
}
public void test(int var1, int var2) {
int var3 = Math.max(var1, var2);
System.out.println(var3);
}
}