ASM exception: Execution can fall off the end of the code create()V

489 views Asked by At

I'm trying to add a new method public void create(){} to a class using ASM framework, however it throws the exception like below:

Exception in thread "main" java.lang.IllegalArgumentException: Execution can fall off the end of the code create()V

at org.objectweb.asm.util.CheckMethodAdapter$1.throwError(CheckMethodAdapter.java:474) at org.objectweb.asm.util.CheckMethodAdapter$1.visitEnd(CheckMethodAdapter.java:462) at org.objectweb.asm.MethodVisitor.visitEnd(MethodVisitor.java:783) at org.objectweb.asm.util.CheckMethodAdapter.visitEnd(CheckMethodAdapter.java:1036) at me.xx2bab.asmdemo.Weaver01AddRemoveFieldAndMethod$onProcess$classVisitor$1.visitEnd(Weaver01AddRemoveFieldAndMethod.kt:41) at org.objectweb.asm.ClassReader.accept(ClassReader.java:715) at org.objectweb.asm.ClassReader.accept(ClassReader.java:394)

here is the code:

        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)

I have tried move super.visitEnd() in front of visitMethod, it throws "Cannot visit member after visitEnd has been called." However the similar operation is working for visitField, like the snippet I comment out.

Not sure what is the true way to implement this requirement..

1

There are 1 answers

0
2BAB On

By the instruction of @Holger from comments, I finally fixed the issue by adding a method body to it:

        // 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()