CodeBlanks Logo Icon CodeBlanks

Bytecode transformation

Write bytecode transformation with ASM.

A transforming visitor

A visitor can wrap another visitor and change the events. This decorator pattern is the basis of ASM agents. A RenameVisitor forwards events to an inner delegate visitor while renaming method names.

For example, if visitMethod does n.replace("main", "start") and forwards to the delegate, the output shows start instead of main. The transformation is transparent: the delegate still runs the same visitor logic.

Wrapping the delegate

RenameVisitor takes a ClassVisitor delegate in its constructor and stores it. On every event it first applies the transformation, then forwards to the delegate. In visitClass it passes the name unchanged, while in visitMethod it can rename.

This pattern is used in ASM agents that transform bytecode: a visitor chain is built, each link adds one operation. The last link is usually a ClassWriter.

Practice Write the RenameVisitor class

Add a class RenameVisitor implements ClassVisitor to the structure above; it has a ClassVisitor delegate field and a RenameVisitor(ClassVisitor delegate) constructor. Its visitClass(String n) method calls delegate.visitClass(n); and visitMethod(String n) calls delegate.visitMethod(n.replace("main", "start"));. In main create ClassWriter writer = new ClassWriter();, call reader.accept(new RenameVisitor(writer)); and print with System.out.println(writer.toString());.

Starter code

Main.java
interface ClassVisitor {
    void visitClass(String name);
    void visitMethod(String name);
}

class ClassReader {
    String name;
    String[] methods;
    ClassReader(String name, String[] methods) {
        this.name = name;
        this.methods = methods;
    }
    void accept(ClassVisitor v) {
        v.visitClass(name);
        for (String m : methods) v.visitMethod(m);
    }
}

class ClassWriter implements ClassVisitor {
    StringBuilder sb = new StringBuilder();
    public void visitClass(String n) { sb.append("Class: ").append(n).append("\n"); }
    public void visitMethod(String n) { sb.append("Method: ").append(n).append("\n"); }
    public String toString() { return sb.toString().trim(); }
}

public class Main {
    public static void main(String[] args) {
        ClassReader reader = new ClassReader("Main", new String[]{"main"});
        ClassWriter writer = new ClassWriter();
        reader.accept(writer);
        System.out.println(writer.toString());
    }
}

Sample solution

Main.java
interface ClassVisitor {
    void visitClass(String name);
    void visitMethod(String name);
}

class ClassReader {
    String name;
    String[] methods;
    ClassReader(String name, String[] methods) {
        this.name = name;
        this.methods = methods;
    }
    void accept(ClassVisitor v) {
        v.visitClass(name);
        for (String m : methods) v.visitMethod(m);
    }
}

class ClassWriter implements ClassVisitor {
    StringBuilder sb = new StringBuilder();
    public void visitClass(String n) { sb.append("Class: ").append(n).append("\n"); }
    public void visitMethod(String n) { sb.append("Method: ").append(n).append("\n"); }
    public String toString() { return sb.toString().trim(); }
}

class RenameVisitor implements ClassVisitor {
    ClassVisitor delegate;
    RenameVisitor(ClassVisitor delegate) {
        this.delegate = delegate;
    }
    public void visitClass(String n) { delegate.visitClass(n); }
    public void visitMethod(String n) { delegate.visitMethod(n.replace("main", "start")); }
}

public class Main {
    public static void main(String[] args) {
        ClassReader reader = new ClassReader("Main", new String[]{"main"});
        ClassWriter writer = new ClassWriter();
        reader.accept(new RenameVisitor(writer));
        System.out.println(writer.toString());
    }
}

Expected output

Class: Main
Method: start

Questions and answers

Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.

1 Complete the rename call

Question
return name.____("main", "start");
Answer
return name.replace("main", "start");

Explanation: name.replace("main", "start") renames the method.

2 What does a transforming visitor do?

  • It forwards altered events Correct answer
  • It compiles bytecode
  • It starts threads
  • It deletes the class

Explanation: A transforming visitor alters events and forwards them to the delegate.

3 Match the transformation elements

Term Meaning
delegate Wrapped visitor
replace Rename
visitMethod Method event
RenameVisitor Transformer class

All lessons in Expert