ASM之FieldVisitor创建变量

7 篇文章 0 订阅

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);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值