1

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!

devoured elysium
  • 101,373
  • 131
  • 340
  • 557

1 Answers1

0

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
Johannes Kuhn
  • 14,778
  • 4
  • 49
  • 73
Eugene Kuleshov
  • 31,461
  • 5
  • 66
  • 67
  • That way they are terrible coupled. I can't, for instance, at run-time to choose which visitors I'd like to run. – devoured elysium Oct 31 '11 at 16:14
  • There is no coupling. The constructor takes a ClassVisitor instance. If you really want to shuffle them at runtime, you can create collection of factories, each factory would take instance of "previous visitor" and create instance of specific visitor for that factory. Pretty simple. Though in my experience I haven't seen use case when something like that would be necessary. – Eugene Kuleshov Nov 01 '11 at 23:11
  • 1
    Think about visitor chain as a "pipe" operator ("|") in shell scripts. Output of previous command can be redirected to the next command. – Eugene Kuleshov Nov 03 '11 at 19:55