How to Fix Java.Lang.VerifyError: Bad Type on Operand Stack

Suraj P Feb 02, 2024
  1. Understand java.lang.VerifyError in Java
  2. Example of java.lang.VerifyError in Java
How to Fix Java.Lang.VerifyError: Bad Type on Operand Stack

In this article, we will learn about java.lang.VerifyError in Java.

Understand java.lang.VerifyError in Java

The java.lang.VerifyError is an error that occurs in the Java Virtual Machine (JVM) during the bytecode verification process. This error is thrown when the JVM detects that the bytecode of a class or method is invalid or violates certain constraints.

There are several reasons why a java.lang.VerifyError might occur:

  1. Incompatible class versions: If a class is compiled with a different version of the Java compiler than the version of the JVM that is trying to run the class, a VerifyError can occur. This can happen if a class is built with a more recent version of Java but is then run on an older JVM.
  2. Incompatible library versions: If a class depends on a library that has a different version than the one the class was compiled with, a VerifyError can occur.
  3. Illegal use of opcodes: If a class or method uses opcodes in an illegal or unsupported way, a VerifyError can occur.
  4. Invalid class file format: If the class file is corrupted or has the wrong format, a VerifyError can occur.
  5. Invalid use of the final keyword: If the final variable is assigned a new value after it’s initialized, a VerifyError can occur.
  6. Using reflection to change the accessibility of a private field/method in a class when a different classloader loads the class.

To fix this error, we will need to find and correct the cause of the problem. This could involve recompiling the class with a compatible version of the Java compiler, updating the library version, or removing any illegal use of opcodes.

If the error is due to the use of reflection, we can avoid it by not changing the accessibility of private fields/methods of a class loaded by a different classloader.

In general, it’s a good practice to be aware of the version of the Java compiler and libraries being used and to test the code with different versions of the JVM to ensure compatibility. Additionally, it’s important to keep the class files and libraries up to date and in good condition to avoid errors like the java.lang.VerifyError.

It’s worth noting that java.lang.VerifyError is a runtime error, and it’s different from java.lang.VerificationError, a compile-time error.

Example of java.lang.VerifyError in Java

Let’s see an example to understand it better.

Example one: Create two Java files, A.java and B.java.

A.java file:

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

B.java file:

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();
  }
}

Now we compile the files:

javac A.java
javac B.java

Both files compile properly without any errors.

However, if we change the definition of the class A to final, and then only recompile the class A and then execute the main method of class B, we get the following error:

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)
     ......
     ......

This error occurs as we have changed the definition of class A, but class B is executed with the older version of class A.

Example two:

Create three Java files, A.java, B.java, and C.java. class B inherits class A and class C contains the main method.

A.java file:

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

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

B.java file:

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 file:

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

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

We compile the Java files separately and then execute the C.java.

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

The execution results in:

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

Now, if we change the definition of the class B not to extend the class A, and then just recompile B.java and then execute the class C, we get the following error:

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

Here again, the error occurs because we have changed the definition of class B, but the class C is executed with the older version of class B.

Author: 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

Related Article - Java Error