exceptions

java.lang.VerifyError – How to solve VerifyError

In this tutorial we will discuss about the VerifyError in Java. This error indicates that the verifier, included in the Java Virtual Machine (JVM), detected a class file that despite well formed, it contains some type of internal inconsistency or faces a security problem.

The VerifyError class extends the LinkageError class, which is used to indicate those error cases, where a class has a dependency on some other class and that class has incompatibly changed after the compilation. Furthermore, the LinkageError class extends the Error class, which is used to indicate those serious problems that an application should not catch. A method may not declare such errors in its throw clause, because these errors are abnormal conditions that shall never occur.

Finally, the VerifyError exists since the 1.0 version of Java.

The Structure of VerifyError

Constructors

  • VerifyError()
  • Creates an instance of the VerifyError class, setting null as its message.

  • VerifyError(String s)
  • Creates an instance of the VerifyError class, using the specified string as message. The string argument indicates the name of the class that threw the error.

The VerifyError in Java

The Java Virtual Machine (JVM) contains a bytecode verifier that is responsible to verify all bytecode before it is executed. The purpose of the bytecode verifier is to verify the integrity of a sequence of bytecodes. The verification procedure consists mostly of the following checks:

  • Branches point to valid locations.
  • Data is initialized and references are type safe.
  • Access to private, or package private, data and methods is controlled.

The first two checks occur when a class is loaded and made eligible for use, while the third check takes place dynamically, when data items or methods of a class are first accessed by another class.

For a more detailed description about the Java Virtual Machine (JVM) verifier please refer to the following sources:

In Java, there are many common cases that throw a VerifyError. In the rest of this section, we will describe some of them in detail.

A class tries to extend a class declared as final:

Consider the following classes:

TestClassA.java:

public class TestClassA {
	public TestClassA() {
		System.out.println("Created a new instance of the TestClassA class");
	}
}

TestClassB.java:

public class TestClassB extends TestClassA {
	public TestClassB() {
		super();
		System.out.println("Created a new instance of the TestClassB class");
	}

	public static void main(String[] args) {
		TestClassB b = new TestClassB();
	}
}

Each class is stored in a separate file. We compile each class separately and then, execute:

$ javac TestClassA.java
$ javac TestClassB.java
$ java TestClassB

A sample execution is shown below:

Created a new instance of the TestClassA class
Created a new instance of the TestClassB class

However, if we change the definition of the class TestClassA to final, then re-compile only the class TestClassA and finally, execute the main method of class TestClassB, the following error is thrown:

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)
	at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
	at java.net.URLClassLoader.defineClass(URLClassLoader.java:455)
	at java.net.URLClassLoader.access$100(URLClassLoader.java:73)
	at java.net.URLClassLoader$1.run(URLClassLoader.java:367)
	at java.net.URLClassLoader$1.run(URLClassLoader.java:361)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.net.URLClassLoader.findClass(URLClassLoader.java:360)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
	at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
	at sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:495)

The cause of the error is that we changed the definition of class TestClassA, but class TestClassB was compiled using an older version of the class TestClassA.

A method tries to override a super method that is declared as final:

Consider the following classes:

TestClassA.java:

public class TestClassA {
	public TestClassA() {
		System.out.println("Created a new instance of the TestClassA class");
	}

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

TestClassB.java:

public class TestClassB extends TestClassA {
	public TestClassB() {
		super();
		System.out.println("Created a new instance of the TestClassB class");
	}

	@Override
	public void print() {
                System.out.println("TestClassB::print()");
        }

	public static void main(String[] args) {
		TestClassB b = new TestClassB();
		b.print();
	}
}

Each class is stored in a separate file. We compile each class separately and then, execute:

$ javac TestClassA.java
$ javac TestClassB.java
$ java TestClassB

A sample execution is shown below:

Created a new instance of the TestClassA class
Created a new instance of the TestClassB class
TestClassB::print()

However, if we change the definition of the method print inside the class TestClassA to final, then re-compile only the class TestClassA and finally, execute the main method of class TestClassB, the following error is thrown:

Exception in thread "main" java.lang.VerifyError: class TestClassB overrides final method print.()V
	at java.lang.ClassLoader.defineClass1(Native Method)
	at java.lang.ClassLoader.defineClass(ClassLoader.java:760)
	at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
	at java.net.URLClassLoader.defineClass(URLClassLoader.java:455)
	at java.net.URLClassLoader.access$100(URLClassLoader.java:73)
	at java.net.URLClassLoader$1.run(URLClassLoader.java:367)
	at java.net.URLClassLoader$1.run(URLClassLoader.java:361)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.net.URLClassLoader.findClass(URLClassLoader.java:360)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
	at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
	at sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:495)

Again, the cause of the error is that we changed a method’s definition of class TestClassA, but class TestClassB was compiled using an older version of the class TestClassA.

A wrong argument is passed to a method:

Consider the following classes:

TestClassA.java:

public class TestClassA {
	public TestClassA() {
		System.out.println("Created a new instance of the TestClassA class");
	}

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

TestClassB.java:

public class TestClassB extends TestClassA {
	public TestClassB() {
		super();
		System.out.println("Created a new instance of the TestClassB class");
	}

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

TestClassC.java:

public class TestClassC {
	public static void _print_(TestClassA a) {
		a.print();
	}

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

Each class is stored in a separate file. We compile each class separately and then, execute:

$ javac TestClassA.java
$ javac TestClassB.java
$ javac TestClassC.java
$ java TestClassC

A sample execution is shown below:

Created a new instance of the TestClassA class
Created a new instance of the TestClassB class
TestClassB::print()

However, if we change the definition of the class TestClassB not to extend the class TestClassA, then re-compile only the class TestClassB and finally, execute the main method of class TestClassC, the following error is thrown:

Exception in thread "main" java.lang.VerifyError: Bad type on operand stack
Exception Details:
  Location:
    TestClassC.main([Ljava/lang/String;)V @9: invokestatic
  Reason:
    Type 'TestClassB' (current frame, stack[0]) is not assignable to 'TestClassA'
  Current Frame:
    bci: @9
    flags: { }
    locals: { '[Ljava/lang/String;', 'TestClassB' }
    stack: { 'TestClassB' }
  Bytecode:
    0x0000000: bb00 0359 b700 044c 2bb8 0005 b1       

	at java.lang.Class.getDeclaredMethods0(Native Method)
	at java.lang.Class.privateGetDeclaredMethods(Class.java:2688)
	at java.lang.Class.privateGetMethodRecursive(Class.java:3035)
	at java.lang.Class.getMethod0(Class.java:3005)
	at java.lang.Class.getMethod(Class.java:1771)
	at sun.launcher.LauncherHelper.validateMainClass(LauncherHelper.java:544)
	at sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:526)

Again, the cause of the error is that we changed the definition of class TestClassB, but class TestClassC was compiled using an older version of the class TestClassB.

How to deal with the VerifyError

In order to avoid the VerifyError, you must compile all your classes using the same version of Java. Also, once you make a change to a class, then make sure that you re-compile your project from scratch. Finally, if your application makes use of external libraries, verify that you use the appropriate version of every library and of course, consult the corresponding javadocs, in order to be sure that everything is correct.

 
This was a tutorial about the VerifyError.zip in Java.

Sotirios-Efstathios Maneas

Sotirios-Efstathios (Stathis) Maneas is a PhD student at the Department of Computer Science at the University of Toronto. His main interests include distributed systems, storage systems, file systems, and operating systems.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Back to top button