02 - ASM组成部分

2022-01-08  本文已影响0人  舍是境界

ASM的两个组成部分

从组成结构上来说,ASM分成两部分,一部分为Core API,另一部分为Tree API。

ASM组成部分

从两者的关系来说,Core API是基础,而Tree API是在Core API的这个基础上构建起来的

Core API概览

这里是对asm.jarasm-util.jarasm-commons.jar文件里包含的主要类成员进行介绍。

asm.jar

在asm.jar文件中,一共包含了30多个类,会重点讲解10个核心类,其他的20多个主要起到“辅助”的作用,它们更多的倾向于是“幕后工作者”;

主要涉及到:ClassVisitorClassWriterFieldVisitorFieldWriterMethodVisitorMethodWriterLabelOpcodesClassReaderType类。

其中最重要的三个类是:ClassVisitorClassWriterClassReader.

类关系图

这三个类的作用,可以简单理解成这样:

asm-util.jar

asm-util.jar主要包含的是一些工具类。这些类主要分成两种类型:Check开头和Trace开头。

asm-util.jar类示意图
asm-commons.jar

asm-commons.jar主要包含的是一些常用功能类。如下图所示,可以看到asm-commons.jar里面包含的具体类文件。

asm-commons.jar核心类

一个非常容易混淆的问题就是,asm-util.jarasm-commons.jar有什么区别呢?在asm-util.jar里,它提供的是通用性的功能,没有特别明确的应用场景;而在asm-commons.jar里,它提供的功能,都是为解决某一种特定场景中出现的问题而提出的解决思路。

搭建ASM开发环境

pom.xml
<properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <java.version>1.8</java.version>
        <maven.compiler.source>${java.version}</maven.compiler.source>
        <maven.compiler.target>${java.version}</maven.compiler.target>
        <asm.version>9.0</asm.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.ow2.asm</groupId>
            <artifactId>asm</artifactId>
            <version>${asm.version}</version>
        </dependency>
        <dependency>
            <groupId>org.ow2.asm</groupId>
            <artifactId>asm-commons</artifactId>
            <version>${asm.version}</version>
        </dependency>
        <dependency>
            <groupId>org.ow2.asm</groupId>
            <artifactId>asm-util</artifactId>
            <version>${asm.version}</version>
        </dependency>
        <dependency>
            <groupId>org.ow2.asm</groupId>
            <artifactId>asm-tree</artifactId>
            <version>${asm.version}</version>
        </dependency>
        <dependency>
            <groupId>org.ow2.asm</groupId>
            <artifactId>asm-analysis</artifactId>
            <version>${asm.version}</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <!-- Java Compiler -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
                <configuration>
                    <source>${java.version}</source>
                    <target>${java.version}</target>
                    <fork>true</fork>
                    <compilerArgs>
                        <arg>-g</arg>
                        <arg>-parameters</arg>
                    </compilerArgs>
                </configuration>
            </plugin>
        </plugins>
    </build>

demo

package com.example;

import org.objectweb.asm.*;

public class HelloWorldDump implements Opcodes {

    public static byte[] dump() {
        ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);

        cw.visit(V1_8, ACC_PUBLIC | ACC_SUPER, "sample/HelloWorld", null, "java/lang/Object", null);

        {
            MethodVisitor mv1 = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
            mv1.visitCode();
            mv1.visitVarInsn(ALOAD, 0);
            mv1.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
            mv1.visitInsn(RETURN);
            mv1.visitMaxs(1, 1);
            mv1.visitEnd();
        }
        {
            MethodVisitor mv2 = cw.visitMethod(ACC_PUBLIC, "toString", "()Ljava/lang/String;", null, null);
            mv2.visitCode();
            mv2.visitLdcInsn("This is HelloWorld object.");
            mv2.visitInsn(ARETURN);
            mv2.visitMaxs(1, 1);
            mv2.visitEnd();
        }
        cw.visitEnd();

        return cw.toByteArray();
    }
}
package com.example;

public class MyClassLoader extends ClassLoader {
    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        if ("sample.HelloWorld".equals(name)) {
            byte[] bytes = HelloWorldDump.dump();
            Class<?> clazz = defineClass(name, bytes, 0, bytes.length);
            return clazz;
        }

        throw new ClassNotFoundException("Class Not Found: " + name);
    }
}
package com.example;

public class HelloWorldRun {
    public static void main(String[] args) throws Exception {
        MyClassLoader classLoader = new MyClassLoader();
        Class<?> clazz = classLoader.loadClass("sample.HelloWorld");
        Object instance = clazz.newInstance();
        System.out.println(instance);
    }
}
输出结果
This is HelloWorld object.

小结

本文主要是对ASM的组成部分进行了介绍,内容总结如下:

希望对你能有所帮助

上一篇 下一篇

猜你喜欢

热点阅读