Java ASM分析方法节点故障

Java ASM分析方法节点故障,java,java-bytecode-asm,bytecode-manipulation,jvm-bytecode,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

我想知道是否可以直接创建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();
                    }
                }
            }
        }
不幸的是,调用
\u analyzer.analyze()时会引发异常:

我相信这是由未设置的
maxStack
maxLocals
造成的。似乎我必须计算正确的
maxStack
maxLocals
,然后在这里调用
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,在此期间让
\u节点直接指向目标MethodNode。这样,整个类节点只有1次访问,即在创建类节点时获取MethodNode


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

无论您试图实现什么,您的“线程安全”代码和局部变量的组合都是不正确的。最明显的是,您将
\u节点
分配两次,第一次分配(这是整个
MethodNode
创建)已过时,而第二次
MethodNode
连接到一个完全本地的
ClassNode
。但无论如何,我们不清楚为什么要处理树API,而实际上只调用访问者方法。如果只使用
ClassWriter
及其
MethodVisitor
,代码会简单得多。当然,每次生成新类时都必须再次调用visit方法,但无论是您还是
ClassNode
MethodNode
在幕后执行,都没有区别。你只是在让你的设计复杂化,没有任何好处。谢谢@Holger。当您说两次分配节点时,您是指第二部分代码吗?在第一部分代码中,
\u节点
仅由
(MethodNode)classNode.visitMethod()赋值,我的问题是第一部分代码。我在文章的末尾加上我的目的。@Holger,对不起,我没有把评论说清楚。第一个是在开头用
/
注释掉。最好删除所有评论,以免混淆。我明白了。我添加了[Java]标记,这样就可以突出显示语法。这也解决了问题。
       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.