ASM depth of the underlying open source framework

What is ASM?

ASM is a Java bytecode manipulation framework. It can be used to dynamically generate the class or classes of existing enhancements. ASM can have a direct binary class files can also be loaded before the Java Virtual Machine dynamically change class behavior in class. Java class is strictly in the format defined in the .class file, class files have metadata store sufficient to resolve all the elements class: class names, methods, properties, and Java byte code (instruction). After the class information from the ASM file is read, it is possible to alter the behavior analysis of class information, a new class can be generated even according to user requirements.

Why dynamically generated Java classes?

Imagine, if you add a variety of open-source framework requires Java class to implement functions such as log, cache, transaction and so on, I think this open source framework you would not use it. Dynamically generated class can reduce intrusion into your code, improve the efficiency of the user.

Why ASM?

The most direct way to transform Java class than the direct overwrite class files. Java specification details the format of class files, directly edit the bytecode can really change the behavior of Java classes. Even today, there are a number of Java experts who use the most primitive tools, such as UltraEdit editor surgery for class files. Yes, this is the most direct method, but requires the user of the Java class file format cooked in mind: carefully calculate the offset of the header function of the relative file you want to transform, but recalculated checksum class file through security mechanisms of the Java virtual machine.

Can be found directly manipulate class file is too much trouble, just why we have chosen to use the same frame, frame shields the complexity of the underlying. ASM is the operating class of a weapon.

Use ASM Programming

ASM provides two API:

  1. CoreAPI(ClassVisitor 、MethodVisitor等)
  2. TreeAPI(ClassNode,MethodNode等)

The difference is CoreAPI event-based model, each element of the definition of the Visitor Class there is no need to load the entire Class into memory. TreeAPI to the entire structure Class Tree structure read into memory. From the point of view TreeAPI easier to use.

The following example uses CoreAPI manner.

Add Maven:


Use is relatively stable, more use version 5.0.4.

First explain, there are many ways to modify Class, for example, directly modify the current Class, or Class of subclassing, so as to achieve an enhanced effect.

The following example is designated by subclassing Class to achieve the effect of enhancing the benefits of the original Class is non-invasive, and can achieve the effect of polymorphism.

First, we define a class to be enhanced:

package com.zjz;

import java.util.Random;

 * @author zhaojz created at 2019-08-22 10:49
public class Student {
    public String name;

    public void studying() throws InterruptedException {
        Thread.sleep(new Random().nextInt(5000));


Next First define a ClassReader:

ClassReader classReader = new ClassReader("com.zjz.Student");

And then define a ClassWriter:

 ClassWriter classWriter = new ClassWriter(classReader, ClassWriter.COMPUTE_MAXS);

ClassWriter.COMPUTE_MAXS represents automatically calculates operand stack and local variable size. More may refer to other options:

Then began an official visit to Class:

ClassVisitor classVisitor = new ClassVisitor(Opcodes.ASM5, classWriter) {
   String enhancedSuperName;
   public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
   String enhancedName = name+"$EnhancedByASM";
   enhancedSuperName = name;
   super.visit(version, access, enhancedName, signature, enhancedSuperName, interfaces);

    public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) {
    System.out.println("Field:" + name);
    return super.visitField(access, name, desc, signature, value);

    public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
    System.out.println("Method:" + name);
    MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions);
    MethodVisitor wrappedMv = mv;
    if (name.equals("studying")) {
    wrappedMv = new StudentStudyingMethodVisitor(Opcodes.ASM5, mv);
    }else if(name.equals("<init>")){
    wrappedMv = new StudentEnhancedConstructorMethodVisitor(Opcodes.ASM5, mv,enhancedSuperName);
    return wrappedMv;

Next, look at the focus MethodVisitor:

static class StudentStudyingMethodVisitor extends MethodVisitor{

    public StudentStudyingMethodVisitor(int i, MethodVisitor methodVisitor) {
    	super(i, methodVisitor);

	//MethodVisitor 中定义了不同的visitXXX()方法,代表的不同的访问阶段。
    public void visitCode() {
        visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/System", "currentTimeMillis", "()J", false);
        visitVarInsn(Opcodes.LSTORE, 1);
        //上面两个的作用就是在Studying方法的第一行添加 long start = System.currentTimeMillis()

	//visitInsn 表示访问进入了方法内部
    public void visitInsn(int opcode) {
    	//通过opcode可以得知当前访问到了哪一步,如果是>=Opcodes.IRETURN && opcode <= Opcodes.RETURN 表明方法即将退出
        if ((opcode >= Opcodes.IRETURN && opcode <= Opcodes.RETURN)){
            visitVarInsn(Opcodes.LLOAD, 1);
            visitMethodInsn(Opcodes.INVOKESTATIC, "com/zjz/Before", "end", "(J)V", false);


static class StudentEnhancedConstructorMethodVisitor extends MethodVisitor{
    private String superClassName;
    public StudentEnhancedConstructorMethodVisitor(int i, MethodVisitor methodVisitor,String superClassName) {
        super(i, methodVisitor);
        this.superClassName = superClassName;

    public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean b) {
        if (opcode==Opcodes.INVOKESPECIAL && name.equals("<init>")){
        	owner = superClassName;
        super.visitMethodInsn(opcode, owner, name, desc, b);

In this case the input data has not ClassVisitor, only defines new output data ClassVisitor (Opcodes.ASM5, classWriter), so it needs:

classReader.accept(classVisitor, ClassReader.SKIP_DEBUG);

This completes the reading of the Class, visit modification process, output.

Attentive viewers will find, and where output to? How to access the new generated classes do? So we need to define a Class ClassLoader to load our generation:

 static class StudentClassLoader extends ClassLoader{
        public Class defineClassFromClassFile(String className,byte[] classFile) throws ClassFormatError{
            return defineClass(className, classFile, 0, classFile.length);

Then acquires the newly generated class byte array by ClassWriter, and loaded into the JVM:

 byte[] data = classWriter.toByteArray();
 Class subStudent = classLoader.defineClassFromClassFile("com.zjz.Student$EnhancedByASM", data);

This completes the generation of a class, the above code completion is a very simple thing: recording learning time.

in conclusion:

ASM CoreAPI core of three things is ClassReader, Visitor, ClassWriter, through the chain of responsibility pattern will link them together.

Visitor access methods, fields, and so on through the attributes of the visitor pattern, if a need to modify the methods and fields and need to be original to the Visitor Wrap click.

hook on the need to understand how the code associated JVM byte code instructions, and the associated OpCode ASM.

ASM Bytecode Outline 2017

But so much instruction, OpCode, symbol remember how to live it? Such as the above code:

visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/System", "currentTimeMillis", "()J", false);
visitVarInsn(Opcodes.LSTORE, 1);

Opcodes.INVOKESTATIC, Opcodes.LSTORE, () J, is not looking dizzy? In fact, in addition to practice makes perfect, you can also use the tool.

If you are using IDEA, you can install plug-ins on ASM Bytecode Outline 2017. Right then select Show Bytecode Outline on the source file, you will see the following view:


ASMified view switching, you'll see the same with the code we wrote above, you can use directly Copy over.

View complete source code examples: asm_demo


Guess you like