首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用bcel构造方法栈图

使用bcel构造方法栈图
EN

Stack Overflow用户
提问于 2014-09-27 07:04:47
回答 1查看 792关注 0票数 0

我正在尝试bcel通过在特定指令之前插入invoke来修改方法。看来我的工具会产生一个不同的堆栈表,bcel包本身不能自动生成它。因此,我的工具化类文件包含旧的stackmap表,这将导致jvm出错。我尝试过使用removeCodeAttributes ( MethodGen的方法)来删除所有的代码属性。它可以在简单的情况下工作,例如包装函数。在我的情况下已经行不通了。

代码语言:javascript
复制
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();
    }
}
EN

回答 1

Stack Overflow用户

发布于 2014-10-20 11:13:22

删除StackMapTable并不是修复错误StackMapTable的适当解决方案。重要的例子是:

4.7.4.StackMapTable属性 在版本号为50.0或以上的class文件中,如果方法的Code属性没有StackMapTable属性,则它具有隐式堆栈映射属性(第4.10.1节)。此隐式堆栈映射属性等效于StackMapTable属性,number_of_entries等于零。

因为StackMapTable必须对每个分支目标都有显式的条目,所以这样的隐式StackMapTable只适用于不带分支的方法。但是在这些情况下,该方法通常没有显式的StackMapTable,因此您就不会遇到这个问题(除非该方法有您的工具删除的分支)。

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

有一个宽限期,JVM支持类文件的回退模式,只有在像您这样的场景中,工具支持并不是最新的。(请参阅-XX:+FailoverToOldVerifier-XX:-UseSplitVerifier)但是宽限期现在已经结束了,这种支持已经被拒绝了,也就是说Java8JVM不再支持回落模式了。

如果您想跟上Java开发和使用这些新版本特性的更新类文件,那么您只有两个选择:

  • 手动计算正确的StackMapTable
  • 使用支持计算正确的StackMapTable属性的工具,例如ASM,(参见java-字节码-asm)支持它
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/26072210

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档