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!
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