java.lang.VerifyError 在构造函数调用中
java.lang.VerifyError on constructor call
我最近开始为我自己的语言编写一个编译器,但是当我调用 main 方法时它开始抛出异常。它与我的其他测试 classes 一起使用,但它不想与这个一起使用。据我所知,此 class 与其他方法的调用方式没有任何不同。这是例外。
Exception in thread "main" java.lang.VerifyError: (class: FizzBuzz/FizzBuzz, method: <init> signature: ()V) Incompatible object argument for function call
at java.lang.Class.getDeclaredMethods0(Native Method)
at java.lang.Class.privateGetDeclaredMethods(Class.java:2693)
at java.lang.Class.privateGetMethodRecursive(Class.java:3040)
at java.lang.Class.getMethod0(Class.java:3010)
at java.lang.Class.getMethod(Class.java:1776)
at sun.launcher.LauncherHelper.validateMainClass(LauncherHelper.java:544)
at sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:526)
这里是 javap
的字节码输出
public final class FizzBuzz.FizzBuzz {
public FizzBuzz.FizzBuzz();
Code:
0: new #16 // class Lang/Int
3: dup
4: lconst_0
5: invokespecial #19 // Method Lang/Int."<init>":(J)V
8: astore_1
9: aload_1
10: new #16 // class Lang/Int
13: dup
14: ldc2_w #20 // long 100l
17: invokespecial #19 // Method Lang/Int."<init>":(J)V
20: invokevirtual #25 // Method Lang/Int._lessThan:(LLang/Number;)LLang/Boolean;
23: getfield #31 // Field Lang/Boolean.value:Z
26: ifeq 140
29: ldc #33 // String
31: astore_2
32: aload_1
33: new #16 // class Lang/Int
36: dup
37: ldc2_w #34 // long 3l
40: invokespecial #19 // Method Lang/Int."<init>":(J)V
43: invokevirtual #39 // Method Lang/Int._modulus:(LLang/Int;)LLang/Int;
46: new #16 // class Lang/Int
49: dup
50: lconst_0
51: invokespecial #19 // Method Lang/Int."<init>":(J)V
54: invokevirtual #43 // Method Lang/Int._equals:(Ljava/lang/Object;)LLang/Boolean;
57: getfield #31 // Field Lang/Boolean.value:Z
60: ifeq 70
63: aload_2
64: ldc #45 // String Fizz
66: invokevirtual #51 // Method Lang/String._add:(LLang/String;)LLang/String;
69: astore_2
70: nop
71: aload_1
72: new #16 // class Lang/Int
75: dup
76: ldc2_w #52 // long 5l
79: invokespecial #19 // Method Lang/Int."<init>":(J)V
82: invokevirtual #39 // Method Lang/Int._modulus:(LLang/Int;)LLang/Int;
85: new #16 // class Lang/Int
88: dup
89: lconst_0
90: invokespecial #19 // Method Lang/Int."<init>":(J)V
93: invokevirtual #43 // Method Lang/Int._equals:(Ljava/lang/Object;)LLang/Boolean;
96: getfield #31 // Field Lang/Boolean.value:Z
99: ifeq 109
102: aload_2
103: ldc #55 // String Buzz
105: invokevirtual #51 // Method Lang/String._add:(LLang/String;)LLang/String;
108: astore_2
109: nop
110: aload_2
111: invokevirtual #59 // Method Lang/String.isEmpty:()LLang/Boolean;
114: invokevirtual #62 // Method Lang/Boolean._not:()LLang/Boolean;
117: getfield #31 // Field Lang/Boolean.value:Z
120: ifeq 127
123: aload_2
124: invokestatic #68 // Method Lang/System.println:(Ljava/lang/Object;)V
127: nop
128: aload_1
129: invokestatic #68 // Method Lang/System.println:(Ljava/lang/Object;)V
132: aload_1
133: invokevirtual #72 // Method Lang/Int._increment:()LLang/Int;
136: astore_1
137: goto 9
140: nop
141: aload_0
142: invokespecial #10 // Method java/lang/Object."<init>":()V
145: return
LocalVariableTable:
Start Length Slot Name Signature
141 5 0 this LFizzBuzz/FizzBuzz;
8 138 1 i LLang/Int;
31 115 2 str LLang/String;
public static void main(java.lang.String[]);
Code:
0: aload_0
1: invokestatic #80 // Method Lang/System.setArguments:([Ljava/lang/String;)V
4: new #4 // class FizzBuzz/FizzBuzz
7: invokespecial #81 // Method "<init>":()V
10: return
LocalVariableTable:
Start Length Slot Name Signature
0 11 0 args [Ljava/lang/String;
}
在你的代码中,你有序列
29: ldc #33 // String
31: astore_2
…
63: aload_2
64: ldc #45 // String Fizz
66: invokevirtual #51 // Method Lang/String._add:(LLang/String;)LLang/String;
当然,仅仅因为您的语言具有不同的 String
类型并不会导致 JVM 在遇到 ldc
指令时使用您的自定义类型。您必须首先将 ldc
指令创建的 java/lang/String
实例转换为 Lang/String
实例。然后你可以调用你的 add
方法。
如果您的自定义 String
是不可变的,并且您想实现您的语言 String
的编译时间常量,您可以使用指向 java/lang/String
的 invokedynamic
指令常量作为静态参数。然后 bootstrap 方法可以将其转换为您的字符串类型和 return 常量方法句柄。由于 bootstrap 方法仅在第一次执行 invokedynamic
指令时调用一次,因此您将获得所需的常量行为。
我最近开始为我自己的语言编写一个编译器,但是当我调用 main 方法时它开始抛出异常。它与我的其他测试 classes 一起使用,但它不想与这个一起使用。据我所知,此 class 与其他方法的调用方式没有任何不同。这是例外。
Exception in thread "main" java.lang.VerifyError: (class: FizzBuzz/FizzBuzz, method: <init> signature: ()V) Incompatible object argument for function call
at java.lang.Class.getDeclaredMethods0(Native Method)
at java.lang.Class.privateGetDeclaredMethods(Class.java:2693)
at java.lang.Class.privateGetMethodRecursive(Class.java:3040)
at java.lang.Class.getMethod0(Class.java:3010)
at java.lang.Class.getMethod(Class.java:1776)
at sun.launcher.LauncherHelper.validateMainClass(LauncherHelper.java:544)
at sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:526)
这里是 javap
的字节码输出public final class FizzBuzz.FizzBuzz {
public FizzBuzz.FizzBuzz();
Code:
0: new #16 // class Lang/Int
3: dup
4: lconst_0
5: invokespecial #19 // Method Lang/Int."<init>":(J)V
8: astore_1
9: aload_1
10: new #16 // class Lang/Int
13: dup
14: ldc2_w #20 // long 100l
17: invokespecial #19 // Method Lang/Int."<init>":(J)V
20: invokevirtual #25 // Method Lang/Int._lessThan:(LLang/Number;)LLang/Boolean;
23: getfield #31 // Field Lang/Boolean.value:Z
26: ifeq 140
29: ldc #33 // String
31: astore_2
32: aload_1
33: new #16 // class Lang/Int
36: dup
37: ldc2_w #34 // long 3l
40: invokespecial #19 // Method Lang/Int."<init>":(J)V
43: invokevirtual #39 // Method Lang/Int._modulus:(LLang/Int;)LLang/Int;
46: new #16 // class Lang/Int
49: dup
50: lconst_0
51: invokespecial #19 // Method Lang/Int."<init>":(J)V
54: invokevirtual #43 // Method Lang/Int._equals:(Ljava/lang/Object;)LLang/Boolean;
57: getfield #31 // Field Lang/Boolean.value:Z
60: ifeq 70
63: aload_2
64: ldc #45 // String Fizz
66: invokevirtual #51 // Method Lang/String._add:(LLang/String;)LLang/String;
69: astore_2
70: nop
71: aload_1
72: new #16 // class Lang/Int
75: dup
76: ldc2_w #52 // long 5l
79: invokespecial #19 // Method Lang/Int."<init>":(J)V
82: invokevirtual #39 // Method Lang/Int._modulus:(LLang/Int;)LLang/Int;
85: new #16 // class Lang/Int
88: dup
89: lconst_0
90: invokespecial #19 // Method Lang/Int."<init>":(J)V
93: invokevirtual #43 // Method Lang/Int._equals:(Ljava/lang/Object;)LLang/Boolean;
96: getfield #31 // Field Lang/Boolean.value:Z
99: ifeq 109
102: aload_2
103: ldc #55 // String Buzz
105: invokevirtual #51 // Method Lang/String._add:(LLang/String;)LLang/String;
108: astore_2
109: nop
110: aload_2
111: invokevirtual #59 // Method Lang/String.isEmpty:()LLang/Boolean;
114: invokevirtual #62 // Method Lang/Boolean._not:()LLang/Boolean;
117: getfield #31 // Field Lang/Boolean.value:Z
120: ifeq 127
123: aload_2
124: invokestatic #68 // Method Lang/System.println:(Ljava/lang/Object;)V
127: nop
128: aload_1
129: invokestatic #68 // Method Lang/System.println:(Ljava/lang/Object;)V
132: aload_1
133: invokevirtual #72 // Method Lang/Int._increment:()LLang/Int;
136: astore_1
137: goto 9
140: nop
141: aload_0
142: invokespecial #10 // Method java/lang/Object."<init>":()V
145: return
LocalVariableTable:
Start Length Slot Name Signature
141 5 0 this LFizzBuzz/FizzBuzz;
8 138 1 i LLang/Int;
31 115 2 str LLang/String;
public static void main(java.lang.String[]);
Code:
0: aload_0
1: invokestatic #80 // Method Lang/System.setArguments:([Ljava/lang/String;)V
4: new #4 // class FizzBuzz/FizzBuzz
7: invokespecial #81 // Method "<init>":()V
10: return
LocalVariableTable:
Start Length Slot Name Signature
0 11 0 args [Ljava/lang/String;
}
在你的代码中,你有序列
29: ldc #33 // String
31: astore_2
…
63: aload_2
64: ldc #45 // String Fizz
66: invokevirtual #51 // Method Lang/String._add:(LLang/String;)LLang/String;
当然,仅仅因为您的语言具有不同的 String
类型并不会导致 JVM 在遇到 ldc
指令时使用您的自定义类型。您必须首先将 ldc
指令创建的 java/lang/String
实例转换为 Lang/String
实例。然后你可以调用你的 add
方法。
如果您的自定义 String
是不可变的,并且您想实现您的语言 String
的编译时间常量,您可以使用指向 java/lang/String
的 invokedynamic
指令常量作为静态参数。然后 bootstrap 方法可以将其转换为您的字符串类型和 return 常量方法句柄。由于 bootstrap 方法仅在第一次执行 invokedynamic
指令时调用一次,因此您将获得所需的常量行为。