java.lang.VerifyError 构造函数调用

标签 java jvm bytecode jvm-languages

我最近开始为我自己的语言编写一个编译器,但是当我调用 main 方法时它开始抛出异常。它适用于我的其他测试类,但它不想使用这个。据我所知,在此类和其他类之间调用方法的方式没有任何不同。这是异常(exception)情况。

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 的编译时间常量,您可以使用 invokedynamic 指令指向到 java/lang/String 常量作为静态参数。然后 Bootstrap 方法可能会将其转换为您的字符串类型并返回一个常量方法句柄。由于 bootstrap 方法仅在第一次执行 invokedynamic 指令时被调用一次,因此您可以获得所需的常量行为。

关于java.lang.VerifyError 构造函数调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32851440/

相关文章:

java - 如何在自定义异常中打印堆栈跟踪?

android - 无法分配内存 : 8 (NetBeans)

java - 使用 janino 将 java 源代码从字符串编译为字节数组中的字节码

java - JVM:如何管理 JNI 创建的堆外内存

java.lang.InternalError : a fault occurred in a recent unsafe memory access operation in compiled Java code 错误

java - 使用 Java var 关键字的缺点

java - JVM上的内存分配是无锁的吗

java - 如何增加Spring WebClient并发请求限制?

java - 如果文件已包含数据,则将数据添加到新行 - Java

java - 如何将Spring-boot服务注入(inject)aspectj类?