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()
VerifyError(String s)
Creates an instance of the VerifyError
class, setting null
as its message.
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.