ASM分析MethodNode失败

时间:2016-02-18 03:28:29

标签: java java-bytecode-asm bytecode-manipulation jvm-bytecode

我想知道我是否可以直接创建MethodNode然后分析它。因此,我在下面编写代码来测试:

        ClassNode classNode = new ClassNode(Opcodes.ASM5);
        classNode.visit(V1_8, ACC_PUBLIC + ACC_SUPER, className, null, Type.getInternalName(BaseTemplate.class), null);

        constructClass(classNode, className);


        //THREAD SAFE but looks badly. 
        if(_node == null){
            synchronized(this){
                if(_node==null){
                    MethodType tmpType = MethodType.methodType(int.class);
                    _node = (MethodNode) classNode.visitMethod(ACC_PUBLIC, Constants.INVOKE_EXACT, tmpType.toMethodDescriptorString(),
                            null, new String[] { "java/lang/Throwable" });
                    _node.visitCode();
                    _node.visitInsn(ICONST_0);
                    _node.visitInsn(IRETURN);
                    //_node.visitMaxs(-1, -1);
                    _node.visitEnd();
                    Analyzer _analyzer = new Analyzer(new SourceInterpreter());
                    try {
                        _analyzer.analyze(className, _node);
                    } catch (AnalyzerException e) {
                        e.printStackTrace();
                    }
                }
            }
        }

不幸的是,调用_analyzer.analyze()时会抛出异常:

java.lang.IndexOutOfBoundsException: Trying to access an inexistant local variable 0
    at org.objectweb.asm.tree.analysis.Frame.setLocal(Frame.java:175) ~[na:5.0.3]
    at org.objectweb.asm.tree.analysis.Analyzer.analyze(Analyzer.java:165) ~[na:5.0.3]
    at java.lang.invoke.MethodHandle.compile(MethodHandle.java:1222) ~[na:na]

我认为这是由maxStackmaxLocals的未设置引起的。我似乎需要计算正确的maxStackmaxLocals,然后在这里调用visitMax()。有没有其他方法没有计算两个值?

我之前使用的另一种方法是代码:

       ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
       cw.visit(V1_8, ACC_PUBLIC + ACC_SUPER, className, null, Type.getInternalName(BaseTemplate.class), null);
       constructClass(cw, className);


            //THREAD SAFE but looks badly.
            if(_node == null){
                    synchronized(this){
                            if(_node==null){
                                    _node = new MethodNode(ACC_PUBLIC, Constants.INVOKE_EXACT, type.toMethodDescriptorString(),
                                        null, new String[] { "java/lang/Throwable" });
                                    generateMethod(_node, className);
                            }
                    }
            }
            _node.accept(cw);
            cw.visitEnd();

             ClassNode classNode = new ClassNode(ASM5);
                    ClassReader reader = new ClassReader(new ByteArrayInputStream(cw.toByteArray()));
                    reader.accept(classNode, 0);

            //Then extract MethodNode from ClassNode and make analyzation. 

这有效,但我不喜欢它,因为它包括多次访问MethodNode。

目的:

我想为每个类实例生成一个MethodNode,每个实例都保留对生成的实例的引用。在第一个代码中,我的想法是直接创建一个ClassNode和目标MethodNode,在此期间让_node直接指向目标MethodNode。通过这种方式,只有1个访问整个ClassNode,即在ClassNode创建期间获取MethodNode。

对于第二部分代码,使用ClassWriter并访问它。在cw.visitEnd()之后,我必须再次访问它以获取ClassNode,即reader.accept(classNode, 0);。有两次访问班级。

0 个答案:

没有答案