美文网首页
10 - ASM使用ClassWrite生成类

10 - ASM使用ClassWrite生成类

作者: 舍是境界 | 来源:发表于2022-01-19 07:11 被阅读0次

生成类

目标
public class HelloWorld {
}
编码实现
import lsieun.utils.FileUtils;
import org.objectweb.asm.*;

import static org.objectweb.asm.Opcodes.*;

public class HelloWorldGenerateCore {
    public static void main(String[] args) throws Exception {
        String relative_path = "sample/HelloWorld.class";
        String filepath = FileUtils.getFilePath(relative_path);

        // (1) 生成byte[]内容
        byte[] bytes = dump();

        // (2) 保存byte[]到文件
        FileUtils.writeBytes(filepath, bytes);
    }

    public static byte[] dump() throws Exception {
        // (1) 创建ClassWriter对象
        ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);

        // (2) 调用visitXxx()方法
        cw.visit(V1_8, ACC_PUBLIC + ACC_SUPER, "sample/HelloWorld",
                null, "java/lang/Object", null);

        MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
        mv.visitCode();
        mv.visitVarInsn(ALOAD, 0);
        mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
        mv.visitInsn(RETURN);
        mv.visitMaxs(1, 1);
        mv.visitEnd();

        cw.visitEnd();

        // (3) 调用toByteArray()方法
        return cw.toByteArray();
    }
}
验证结果
public class HelloWorldRun {
    public static void main(String[] args) throws Exception {
        Class<?> clazz = Class.forName("sample.HelloWorld");
        System.out.println(clazz);
    }
}

<init>()和<clinit>()方法

对于一个类(Class)来说,如果没有提供任何构造方法,Java编译器会自动生成一个默认构造方法。在所有的.class文件中,构造方法的名字是<init>()。

另外,如果在.class文件中包含静态代码块,那么就会有一个<clinit>()方法。

package sample;

public class HelloWorld {
    static {
        System.out.println("static code block");
    }
}

上面的静态代码码,对应于visitMethod(ACC_STATIC, "<clinit>", "()V", null, null)的调用。

小结

通过三篇文章我们主要对ClassWriter类的代码示例进行介绍,主要目的是希望大家能够对ClassWriter类熟悉起来,内容总结如下:

  • 第一点,我们需要注意ClassWriter/ClassVisitor中visit()、visitField()、visitMethod()和visitEnd()方法的调用顺序。
  • 第二点,我们对于visit()方法、visitField()方法和visitMethod()方法接收的参数进行了介绍。虽然我们并没有特别介绍visitEnd()方法和toByteArray()方法,并不表示这两个方法不重要,只是因为这两个方法不接收任何参数。
  • 第三点,我们介绍了Internal Name和Descriptor(描述符)这两个概念,在使用时候需要加以注意,因为它们与我们在使用Java语言编写代码时是不一样的。
  • 第四点,在.class文件中,构造方法的名字是<init>(),表示instance initialization method;静态代码块的名字是<clinit>(),表示class initialization method。
  • 另外,visitField()方法会返回一个FieldVisitor对象,而visitMethod()方法会返回一个MethodVisitor对象;在后续的内容当中,我们会分别介绍FieldVisitor类和MethodVisitor类。

相关文章

  • 10 - ASM使用ClassWrite生成类

    生成类 目标 编码实现 验证结果 ()和()方法 对于一个类(Class)来说,如果没...

  • 08 - ASM使用ClassWrite生成接口

    生成接口 目标:生成如下接口 编码实现 在上述代码中,我们调用了visit()方法、visitEnd()方法和to...

  • 09 - ASM使用ClassWrite生成接口+字段+方法

    生成接口+字段+方法 目标 编码实现 在上述代码中,我们调用了visit()方法、visitField()方法、v...

  • JAVA中ASM是什么?

    什么是 ASM ? ASM 是一个 Java 字节码操控框架。它能被用来动态生成类或者增强既有类的功能。ASM 可...

  • 深入开源框架底层之ASM

    什么是 ASM ? ASM 是一个 Java 字节码操控框架。它能被用来动态生成类或者增强既有类的功能。ASM 可...

  • 简单看看ASM框架

    什么是ASM ASM 是一个 Java 字节码操控框架。它能被用来动态生成类或者增强既有类的功能。ASM 可以直接...

  • 43 AOP(面向切面编程)-ASM-2

    1. ASM 介绍 ASM 是一个 Java 字节码操作框架,它能用来动态生成类或者增强既有类的功能。ASM 可以...

  • [转载]AOP 的利器:ASM 3.0 介绍

    引言 什么是 ASM ? ASM 是一个 Java 字节码操控框架。它能被用来动态生成类或者增强既有类的功能。AS...

  • AOP之利器:ASM介绍

    什么是ASM? ASM是一个字节码操控框架。它能被用来动态生成类,或者增强既有类的功能。ASM可以直接产生二进制c...

  • ASM简介(六)

    TreeAPI Class ASM中修改生成class主要依赖ClassNode类 生成class时我们只需构造对...

网友评论

      本文标题:10 - ASM使用ClassWrite生成类

      本文链接:https://www.haomeiwen.com/subject/iiuvcrtx.html