Простой способ собрать пару посетителей ASM-Bytecode?

В настоящее время я реализую некоторый код, который должен для каждого метода класса запускать пару посетителей в файле .class, чтобы инструментировать его байт-код. На данный момент я только что реализовал MethodRenamerVisitor, но это уже становится довольно неловко:

    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();
    }

Сейчас я хочу привлечь других посетителей к каждому из методов BytecodeMethods. Я слишком усложняю это? Было бы идеально, если бы я мог иметь что-то вроде:

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

поэтому я мог бы легко сложить всех посетителей, которых я хочу запустить, и только в конце мне пришлось бы сохранять их на диск. Имейте в виду, что каждый из посетителей будет добавлять/удалять/изменять методы, которые он посещает!


person devoured elysium    schedule 30.10.2011    source источник


Ответы (1)


У вас уже есть два посетителя — ClassWriter и MethodRenamerVisitor. В основном следующий посетитель в цепочке передается как первый параметр i конструктора. Таким образом, третий можно добавить следующим образом:

ThirdVisitor v3 = new ThirdVisitor(methodRenamerVisitor);
ForthVisitor v4 = new ForthVisitor(v3);
// etc
person Eugene Kuleshov    schedule 31.10.2011
comment
Таким образом, они ужасны в паре. Я не могу, например, во время выполнения выбрать, каких посетителей я хотел бы запускать. - person devoured elysium; 31.10.2011
comment
Сцепления нет. Конструктор принимает экземпляр ClassVisitor. Если вы действительно хотите перетасовать их во время выполнения, вы можете создать коллекцию фабрик, каждая фабрика будет брать экземпляр предыдущего посетителя и создавать экземпляр конкретного посетителя для этой фабрики. Довольно просто. Хотя на своем опыте я не видел случая использования, когда что-то подобное было бы необходимо. - person Eugene Kuleshov; 02.11.2011
comment
Думайте о цепочке посетителей как об операторе канала (|) в сценариях оболочки. Вывод предыдущей команды может быть перенаправлен на следующую команду. - person Eugene Kuleshov; 03.11.2011