堆叠ASM访问者的正确方法是什么?

问题描述 投票:1回答:1

我有以下代码:

for (Map.Entry<String, ClassReader> e : classes.entrySet())
{
    ClassReader reader = e.getValue();
    ClassWriter writer = new ClassWriter(Opcodes.ASM7);

    // Process all visitors
    reader.accept(new StringRemapper(writer, "String A", "String A!!"), ClassReader.EXPAND_FRAMES);
    reader.accept(new StringRemapper(writer, "String B", "String B!!"), ClassReader.EXPAND_FRAMES);

    // Update the class
    reader = new ClassReader(writer.toByteArray());
    e.setValue(reader);
}

上面的代码的问题在于,它会将所有内容写两次,因为有两个访问者正在向同一位作者写信(我想)。

要解决此问题,我需要在每个reader.accept之后添加以下代码:

reader = new ClassReader(writer.toByteArray());
writer = new ClassWriter(Opcodes.ASM7);

这样做是在滥用访客模式吗?我的意思是,为什么我需要创建一个新的读者/作家并仅访问一次?我不应该可以有多个访客吗?

我发现了类似的问题Easy way to stack up a couple of ASM-Bytecode visitors?,但无法理解接受的答案。

我试图将第一个访问者作为参数传递给第二个访问者,而不是原始的ClassWriter,其结果相同,代码重复。

ClassVisitor last;
// Process all visitors
reader.accept(last = new StringRemapper(writer, "String A", "String A!!"), ClassReader.EXPAND_FRAMES);
reader.accept(new StringRemapper(last, "String B", "String B!!"), ClassReader.EXPAND_FRAMES);
java bytecode java-bytecode-asm
1个回答
0
投票

您是对的,您确实错过了一些事情:ClassWriter本身就是ClassVisitor

堆叠访问者的正确方法是将其父访问者传递给构造函数:

// The root visitor is the ClassWriter
ClassVisitor cv = writer;

// Add a visitor
cv = new StringRemapper(cv, "String A", "String A!!");
// Add an other
cv = new StringRemapper(cv, "String B", "String B!!");
// maybe add more?

// process them
reader.accept(cv, ClassReader.EXPAND_FRAMES);
byte[] classFile = writer.toByteArray();

如果StringRemapper仅采用ClassWriter作为参数,则应更改它以接受ClassVisitor的读入。

[我注意到的另一件事是您的classes变量:它包含ClassReader作为值。将ClassVisitors用作值-具有初始ClassWriter值可能更容易设计。但这是一个更大的设计更改。

© www.soinside.com 2019 - 2024. All rights reserved.