JVM 验证错误 'Illegal type at constant pool'
JVM Verify Error 'Illegal type at constant pool'
我目前正在编写自己的编译器,我正在尝试编译以下代码:
List[String] list = List("a", "b", "c", "d")
list stream map((String s) => s.toUpperCase())
System out println list
编译器解析、链接或编译代码没有问题,但在执行时,JVM 抛出以下错误:
java.lang.VerifyError: Illegal type at constant pool entry 40 in class dyvil.test.Main
Exception Details:
Location:
dyvil/test/Main.main([Ljava/lang/String;)V @29: invokevirtual
Reason:
Constant pool index 40 is invalid
Bytecode:
...
我尝试使用javap
来查找问题,这是指令@29
:
29: invokevirtual #40 // InterfaceMethod java/util/Collection.stream:()Ljava/util/stream/Stream;
常量池中的条目(也使用javap
):
#37 = Utf8 stream
#38 = Utf8 ()Ljava/util/stream/Stream;
#39 = NameAndType #37:#38 // stream:()Ljava/util/stream/Stream;
#40 = InterfaceMethodref #36.#39 // java/util/Collection.stream:()Ljava/util/stream/Stream;
使用 Eclipse Class 文件查看器打开 class 时,@29
所在的行应为:
Class Format Exception
并且所有后续说明都不再显示(除了 Locals,...)。然而,ASM 字节码插件写
INVOKEVIRTUAL java/util/Collection.stream ()Ljava/util/stream/Stream;
在那一行,这似乎是有效的。我在这里做错了什么/遗漏了什么?
我发现了我的错误。错误在这里:
invokevirtual #40 // InterfaceMethod
^^^^^^^ ^^^^^^^^^
我在 interface 方法上使用 invokevirtual,这通常不是一个好主意。不过我觉得验证者抛出的错误应该更清楚到底是哪里出了问题。
使用 ASM,您会看到此错误,因为 isInterface
标志不正确。 visitMethodInsn
的参数 isInterface
指的是 target/owner/destination 而不是当前上下文。
i.o.w当使用INVOKEVIRTUAL
时,isInterface
是假的。
有关详细信息,请参阅 issue here。
我目前正在编写自己的编译器,我正在尝试编译以下代码:
List[String] list = List("a", "b", "c", "d")
list stream map((String s) => s.toUpperCase())
System out println list
编译器解析、链接或编译代码没有问题,但在执行时,JVM 抛出以下错误:
java.lang.VerifyError: Illegal type at constant pool entry 40 in class dyvil.test.Main
Exception Details:
Location:
dyvil/test/Main.main([Ljava/lang/String;)V @29: invokevirtual
Reason:
Constant pool index 40 is invalid
Bytecode:
...
我尝试使用javap
来查找问题,这是指令@29
:
29: invokevirtual #40 // InterfaceMethod java/util/Collection.stream:()Ljava/util/stream/Stream;
常量池中的条目(也使用javap
):
#37 = Utf8 stream
#38 = Utf8 ()Ljava/util/stream/Stream;
#39 = NameAndType #37:#38 // stream:()Ljava/util/stream/Stream;
#40 = InterfaceMethodref #36.#39 // java/util/Collection.stream:()Ljava/util/stream/Stream;
使用 Eclipse Class 文件查看器打开 class 时,@29
所在的行应为:
Class Format Exception
并且所有后续说明都不再显示(除了 Locals,...)。然而,ASM 字节码插件写
INVOKEVIRTUAL java/util/Collection.stream ()Ljava/util/stream/Stream;
在那一行,这似乎是有效的。我在这里做错了什么/遗漏了什么?
我发现了我的错误。错误在这里:
invokevirtual #40 // InterfaceMethod
^^^^^^^ ^^^^^^^^^
我在 interface 方法上使用 invokevirtual,这通常不是一个好主意。不过我觉得验证者抛出的错误应该更清楚到底是哪里出了问题。
使用 ASM,您会看到此错误,因为 isInterface
标志不正确。 visitMethodInsn
的参数 isInterface
指的是 target/owner/destination 而不是当前上下文。
i.o.w当使用INVOKEVIRTUAL
时,isInterface
是假的。
有关详细信息,请参阅 issue here。