gpt4 book ai didi

java - 使用 bcel 时构造方法的堆栈图

转载 作者:行者123 更新时间:2023-12-02 05:25:33 30 4
gpt4 key购买 nike

我正在尝试通过在特定指令之前插入调用来修改方法。看来我的检测会产生不同的堆栈映射表,该表无法由 bcel 包本身自动生成。因此,我的检测类文件包含旧的堆栈映射表,这会导致 jvm 错误。我尝试过使用MethodGen的方法removeCodeAttributes,它可以删除所有代码属性。它可以在简单的情况下工作,例如包装函数。现在它不适用于我的情况。

public class Insert{
public static void main(String[] args) throws ClassFormatException, IOException{
Insert isrt = new Insert();
String className = "StringBuilder.class";
JavaClass jclzz = new ClassParser(className).parse();
ClassGen cgen = new ClassGen(jclzz);
ConstantPoolGen cpgen = cgen.getConstantPool();
MethodGen mgen = new MethodGen(jclzz.getMethods()[1], className, cpgen);
InstructionFactory ifac = new InstructionFactory(cgen);
InstructionList ilist = mgen.getInstructionList();
for (InstructionHandle ihandle : ilist.getInstructionHandles()){
System.out.println(ihandle.toString());
}
InstructionFinder f = new InstructionFinder(ilist);
InstructionHandle[] insert_pos = (InstructionHandle[])(f.search("invokevirtual").next());
Instruction inserted_inst = ifac.createInvoke("java.lang.System", "currentTimeMillis", Type.LONG, Type.NO_ARGS, Constants.INVOKESTATIC);
System.out.println(inserted_inst.toString());
ilist.insert(insert_pos[0], inserted_inst);


mgen.setMaxStack();
mgen.setMaxLocals();


mgen.removeCodeAttributes();
cgen.replaceMethod(jclzz.getMethods()[1], mgen.getMethod());

ilist.dispose();
//output the file
FileOutputStream fos = new FileOutputStream(className);
cgen.getJavaClass().dump(fos);
fos.close();
}
}

最佳答案

删除 StackMapTable 并不是修复错误 StackMapTable 的正确解决方案。重要的引用是:

4.7.4. The StackMapTable Attribute

In a class file whose version number is 50.0 or above, if a method's Code attribute does not have a StackMapTable attribute, it has an implicit stack map attribute (§4.10.1). This implicit stack map attribute is equivalent to a StackMapTable attribute with number_of_entries equal to zero.

由于 StackMapTable 必须为每个分支目标具有显式条目,因此此类隐式 StackMapTable 仅适用于无分支方法。但在这些情况下,该方法通常没有显式的 StackMapTable,因此您不会遇到该问题(除非该方法具有您的检测删除的分支)。

另一个结论是,如果您将类文件版本号修补为低于50的值,则可以不用删除StackMapTable 。当然,如果您不需要 50 或更高版本中引入的任何类文件功能,这只是一个解决方案......

有一个宽限期,其中 JVM 支持对 StackMapTable 损坏的类文件使用回退模式,仅适用于像您这样的场景,其中工具支持不是最新的。 (请参阅 -XX:+FailoverToOldVerifier-XX:-UseSplitVerifier )但宽限期现已结束,并且该支持已被拒绝,即 Java 8 JVM 不再支持回退模式。

如果您想跟上 Java 开发并使用可能使用这些新版本功能的新类文件,您只有两个选择:

  • 手动计算正确的StackMapTable
  • 使用支持计算正确的 StackMapTable 属性的工具,例如ASM,(参见 )确实支持它

关于java - 使用 bcel 时构造方法的堆栈图,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26072210/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com