Java.Lang.VerifyError: Fehlerhafter Typ im Operandenstapel

Suraj P 12 Oktober 2023
  1. Verstehen Sie java.lang.VerifyError in Java
  2. Beispiel für java.lang.VerifyError in Java
Java.Lang.VerifyError: Fehlerhafter Typ im Operandenstapel

In diesem Artikel lernen wir etwas über java.lang.VerifyError in Java.

Verstehen Sie java.lang.VerifyError in Java

Der java.lang.VerifyError ist ein Fehler, der in der Java Virtual Machine (JVM) während des Bytecode-Verifizierungsprozesses auftritt. Dieser Fehler wird ausgegeben, wenn die JVM feststellt, dass der Bytecode einer Klasse oder Methode ungültig ist oder gegen bestimmte Einschränkungen verstößt.

Es gibt mehrere Gründe, warum ein java.lang.VerifyError auftreten kann:

  1. Inkompatible Klassenversionen: Wenn eine Klasse mit einer anderen Version des Java-Compilers kompiliert wird als die Version der JVM, die versucht, die Klasse auszuführen, kann ein VerifyError auftreten. Dies kann passieren, wenn eine Klasse mit einer neueren Java-Version erstellt wird, aber dann auf einer älteren JVM ausgeführt wird.
  2. Inkompatible Bibliotheksversionen: Wenn eine Klasse von einer Bibliothek abhängt, die eine andere Version hat als die, mit der die Klasse kompiliert wurde, kann ein VerifyError auftreten.
  3. Illegale Verwendung von Opcodes: Wenn eine Klasse oder Methode Opcodes auf illegale oder nicht unterstützte Weise verwendet, kann ein VerifyError auftreten.
  4. Ungültiges Klassendateiformat: Wenn die Klassendatei beschädigt ist oder das falsche Format hat, kann ein VerifyError auftreten.
  5. Unzulässige Verwendung des Schlüsselwortes final: Wird der Variable final nach der Initialisierung ein neuer Wert zugewiesen, kann ein VerifyError auftreten.
  6. Verwenden von Reflektion, um die Zugänglichkeit eines privaten Felds/einer privaten Methode in einer Klasse zu ändern, wenn ein anderer classloader die Klasse lädt.

Um diesen Fehler zu beheben, müssen wir die Ursache des Problems finden und beheben. Dies könnte das erneute Kompilieren der Klasse mit einer kompatiblen Version des Java-Compilers, das Aktualisieren der Bibliotheksversion oder das Entfernen jeglicher illegaler Verwendung von Opcodes beinhalten.

Wenn der Fehler auf die Verwendung von Reflektion zurückzuführen ist, können wir ihn vermeiden, indem wir die Zugänglichkeit von privaten Feldern/Methoden einer Klasse, die von einem anderen classloader geladen wurden, nicht ändern.

Im Allgemeinen empfiehlt es sich, die Version des verwendeten Java-Compilers und der verwendeten Bibliotheken zu kennen und den Code mit verschiedenen Versionen der JVM zu testen, um die Kompatibilität sicherzustellen. Außerdem ist es wichtig, die Klassendateien und Bibliotheken aktuell und in gutem Zustand zu halten, um Fehler wie den java.lang.VerifyError zu vermeiden.

Es ist erwähnenswert, dass java.lang.VerifyError ein Laufzeitfehler ist und sich von java.lang.VerificationError, einem Kompilierungsfehler, unterscheidet.

Beispiel für java.lang.VerifyError in Java

Sehen wir uns ein Beispiel an, um es besser zu verstehen.

Beispiel eins: Erstellen Sie zwei Java-Dateien, A.java und B.java.

A.java-Datei:

public class A {
  public A() {
    System.out.println("Instance of A is created");
  }
}

B.java-Datei:

public class B extends A {
  public B() {
    super();
    System.out.println("Instance of B is created");
  }

  public static void main(String[] args) {
    B obj = new B();
  }
}

Jetzt kompilieren wir die Dateien:

javac A.java
javac B.java

Beide Dateien werden ordnungsgemäß und ohne Fehler kompiliert.

Wenn wir jedoch die Definition der class A auf final ändern, und dann nur die class A neu kompilieren und dann die main-Methode von class B ausführen, erhalten wir folgenden Fehler:

Exception in thread "main" java.lang.VerifyError: Cannot inherit from final class
    at java.lang.ClassLoader.defineClass1(Native Method)
    at java.lang.ClassLoader.defineClass(ClassLoader.java:760)
     ......
     ......

Dieser Fehler tritt auf, weil wir die Definition von Klasse A geändert haben, aber Klasse B mit der älteren Version von Klasse A ausgeführt wird.

Beispiel zwei:

Erstellen Sie drei Java-Dateien, A.java, B.java und C.java. class B erbt class A und class C enthält die main-Methode.

A.java-Datei:

public class A {
  public A() {
    System.out.println("Class A instance is created");
  }

  public void print() {
    System.out.println("A::print()");
  }
}

B.java-Datei:

public class B extends A {
  public B() {
    super();
    System.out.println("Class B instance is created");
  }

  public void print() {
    System.out.println("B::print()");
  }
}

C.java-Datei:

public class C {
  public static void _print_(A obj) {
    obj.print();
  }

  public static void main(String[] args) {
    B b = new B();
    C._print_(b);
  }
}

Wir kompilieren die Java-Dateien separat und führen dann das C.java aus.

javac A.java
javac B.java
javac C.java
java C

Die Ausführung ergibt:

Class A instance is created
Class B instance is created
B::print()

Wenn wir nun die Definition der Klasse B ändern, um die Klasse A nicht zu erweitern, und dann einfach B.java neu kompilieren und dann die Klasse C ausführen, erhalten wir die folgende Fehlermeldung:

Exception in thread "main" java.lang.VerifyError: Bad type on operand stack
Exception Details:
  ....
  ....

Auch hier tritt der Fehler auf, weil wir die Definition von class B geändert haben, aber die class C mit der älteren Version von class B ausgeführt wird.

Autor: Suraj P
Suraj P avatar Suraj P avatar

A technophile and a Big Data developer by passion. Loves developing advance C++ and Java applications in free time works as SME at Chegg where I help students with there doubts and assignments in the field of Computer Science.

LinkedIn GitHub

Verwandter Artikel - Java Error