Search code examples
javabytecodejava-bytecode-asm

Easy way to stack up a couple of ASM-Bytecode visitors?


I'm currently implementing some code that should, for each method of a class, run a couple of visitors on a .class file, as to instrument its bytecode. At the moment, I've just implemented a MethodRenamerVisitor, but this is already getting quite awkward:

    ClassReader classReader = null;
    try {
        classReader = new ClassReader(monitoringFile.getCannonicalName());
    } catch (IOException e1) {
        e1.printStackTrace();
    }

    ClassWriter classWriter = null;

    for (BytecodeMethod bytecodeMethod : bytecodeClass.bytecodeMethods) {
        System.out.println("\t" + bytecodeMethod.getName());

        classWriter = new ClassWriter(ClassWriter.COMPUTE_FRAMES);

        MethodRenamerVisitor methodRenamerVisitor = new MethodRenamerVisitor(classWriter, bytecodeMethod);
        classReader.accept(methodRenamerVisitor, 0);

        String outputFile = monitoringFile.getCannonicalName();
        outputFile = outputFile.replace('.', File.separatorChar)+".class";

        classReader = new ClassReader(classWriter.toByteArray());
    }

    try {
        fileSystem.writeToDisk(
                classFilename,
                classWriter.toByteArray()
                );
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }

I'm now in the process of wanting to apply other visitors to each one of the BytecodeMethods. Am I over-complicating this? It'd be ideal if I could have something of the form of:

MultiVisitors multiVisitors = new MultiVisitors();
visitors.add(new AVisitor(...));
visitors.add(new BVisitor(...));
...
visitors.run();

so I could easily stack all the visitors I want to run and then only in the end I'd have to save them on disk. Keep in mind that each one of the visitors will add/remove/modify the methods it is visiting!


Solution

  • You already stacking up two visitors - ClassWriter and MethodRenamerVisitor. Basically the next visitor in the chain is passed as first parameter i constructor. So the third one can be added like this:

    ThirdVisitor v3 = new ThirdVisitor(methodRenamerVisitor);
    ForthVisitor v4 = new ForthVisitor(v3);
    // etc