asm异常:执行可能会从代码create()v的末尾掉下来

wixjitnu  于 2021-07-03  发布在  Java
关注(0)|答案(1)|浏览(315)

我正在尝试添加一个新方法 public void create(){} 对于使用asm框架的类,它抛出如下异常:
线程“main”java.lang.illegalargumentexception中出现异常:执行可能会从代码create()v的末尾脱落
在org.objectweb.asm.util.checkmethodadapter$1.throwerror(checkmethodadapter。java:474)在org.objectweb.asm.util.checkmethodadapter$1.visitend(checkmethodadapter。java:462)在org.objectweb.asm.methodvisitor.visitend(methodvisitor。java:783)在org.objectweb.asm.util.checkmethodadapter.visitend(checkmethodadapter。java:1036)在me.xx2bab.asmdemo.weaver01addremovefieldandmethod$onprocess$classvisitor$1.visitend(weaver01addremovefieldandmethod.kt:41)位于org.objectweb.asm.classreader.accept(classreader)。java:715)在org.objectweb.asm.classreader.accept(classreader。java:394)
代码如下:

val classReader = ClassReader(inputStream)
        val classWriter = ClassWriter(classReader, COMPUTE_FRAMES or COMPUTE_MAXS)
        val classVisitor = object : ClassVisitor(ASM9, CheckClassAdapter(classWriter, true)) {
            override fun visitEnd() {
//                visitField(
//                    Opcodes.ACC_PUBLIC,
//                    "newFieldName",
//                    "Ljava/lang/String;",
//                    null,
//                    null
//                ).visitEnd()
                visitMethod(
                    Opcodes.ACC_PUBLIC,
                    "create",
                    "()V",
                    null,
                    null
                )?.visitEnd() // This is where exception throws
                super.visitEnd()
            }

        }
        classReader.accept(classVisitor, 0)

我试过搬家 super.visitEnd() 在前面 visitMethod ,它抛出“调用visitend后无法访问成员”。但是,类似的操作也适用于 visitField ,就像我注解掉的片段。
不确定实现这一要求的真正方法是什么。。

ykejflvf

ykejflvf1#

根据@holger from comments的指示,我最终通过添加一个方法体解决了这个问题:

// Add a new method
        val mv = classWriter.visitMethod(
            Opcodes.ACC_PUBLIC,
            "create",
            "()V",
            null,
            null
        )
        mv.visitFieldInsn(
            GETSTATIC,
            "java/lang/System",
            "out",
            "Ljava/io/PrintStream;"
        )
        mv.visitLdcInsn("this is add method print!")
        mv.visitMethodInsn(
            INVOKEVIRTUAL,
            "java/io/PrintStream",
            "println",
            "(Ljava/lang/String;)V",
            false
        )
        mv.visitInsn(RETURN)
        // this code uses a maximum of two stack elements and two local
        // variables
        mv.visitMaxs(0, 0)
        mv.visitEnd()

        return classWriter.toByteArray()

相关问题