【问题标题】:ASM exception: Execution can fall off the end of the code create()VASM 异常:执行可能会从代码 create()V 的末尾脱落
【发布时间】:2020-12-04 10:18:45
【问题描述】:

我正在尝试向使用 ASM 框架的类添加新方法 public void create(){},但它会引发如下异常:

线程“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)

我尝试在visitMethod 前面移动super.visitEnd(),它抛出“调用visitEnd 后无法访问成员。”然而,类似的操作适用于visitField,就像我注释掉的 sn-p。

不确定实现此要求的真正方法是什么..

【问题讨论】:

  • 您不能在不提供代码的情况下创建非abstract 方法。将您未提供的代码视为空指令序列时,缺少的 return 或 throw 指令将导致“execution can fall off the end of the code”错误。当然,这不会发生在字段上,因为字段没有代码。

标签: java kotlin assembly bytecode jvm-bytecode


【解决方案1】:

在 cmets 的@Holger 的指导下,我终于通过添加方法体解决了这个问题:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-26
    • 1970-01-01
    • 2015-04-20
    • 2013-01-09
    • 2020-08-02
    相关资源
    最近更新 更多