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:
1 | public class TestClassA { |
3 | System.out.println("Created a new instance of the TestClassA class"); |
TestClassB.java:
01 | public class TestClassB extends TestClassA { |
04 | System.out.println("Created a new instance of the TestClassB class"); |
07 | public static void main(String[] args) { |
08 | TestClassB b = new TestClassB(); |
Each class is stored in a separate file. We compile each class separately and then, execute:
A sample execution is shown below:
1 | Created a new instance of the TestClassA class |
2 | 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:
01 | Exception in thread "main" java.lang.VerifyError: Cannot inherit from final class |
02 | at java.lang.ClassLoader.defineClass1(Native Method) |
03 | at java.lang.ClassLoader.defineClass(ClassLoader.java:760) |
04 | at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142) |
05 | at java.net.URLClassLoader.defineClass(URLClassLoader.java:455) |
06 | at java.net.URLClassLoader.access$100(URLClassLoader.java:73) |
07 | at java.net.URLClassLoader$1.run(URLClassLoader.java:367) |
08 | at java.net.URLClassLoader$1.run(URLClassLoader.java:361) |
09 | at java.security.AccessController.doPrivileged(Native Method) |
10 | at java.net.URLClassLoader.findClass(URLClassLoader.java:360) |
11 | at java.lang.ClassLoader.loadClass(ClassLoader.java:424) |
12 | at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308) |
13 | at java.lang.ClassLoader.loadClass(ClassLoader.java:357) |
14 | 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:
1 | public class TestClassA { |
3 | System.out.println("Created a new instance of the TestClassA class"); |
7 | System.out.println("TestClassA::print()"); |
TestClassB.java:
01 | public class TestClassB extends TestClassA { |
04 | System.out.println("Created a new instance of the TestClassB class"); |
09 | System.out.println("TestClassB::print()"); |
12 | public static void main(String[] args) { |
13 | TestClassB b = new TestClassB(); |
Each class is stored in a separate file. We compile each class separately and then, execute:
A sample execution is shown below:
1 | Created a new instance of the TestClassA class |
2 | Created a new instance of the TestClassB class |
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:
01 | Exception in thread "main" java.lang.VerifyError: class TestClassB overrides final method print.()V |
02 | at java.lang.ClassLoader.defineClass1(Native Method) |
03 | at java.lang.ClassLoader.defineClass(ClassLoader.java:760) |
04 | at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142) |
05 | at java.net.URLClassLoader.defineClass(URLClassLoader.java:455) |
06 | at java.net.URLClassLoader.access$100(URLClassLoader.java:73) |
07 | at java.net.URLClassLoader$1.run(URLClassLoader.java:367) |
08 | at java.net.URLClassLoader$1.run(URLClassLoader.java:361) |
09 | at java.security.AccessController.doPrivileged(Native Method) |
10 | at java.net.URLClassLoader.findClass(URLClassLoader.java:360) |
11 | at java.lang.ClassLoader.loadClass(ClassLoader.java:424) |
12 | at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308) |
13 | at java.lang.ClassLoader.loadClass(ClassLoader.java:357) |
14 | 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:
1 | public class TestClassA { |
3 | System.out.println("Created a new instance of the TestClassA class"); |
7 | System.out.println("TestClassA::print()"); |
TestClassB.java:
01 | public class TestClassB extends TestClassA { |
04 | System.out.println("Created a new instance of the TestClassB class"); |
08 | System.out.println("TestClassB::print()"); |
TestClassC.java:
01 | public class TestClassC { |
02 | public static void _print_(TestClassA a) { |
06 | public static void main(String[] args) { |
07 | TestClassB b = new TestClassB(); |
08 | TestClassC._print_(b); |
Each class is stored in a separate file. We compile each class separately and then, execute:
A sample execution is shown below:
1 | Created a new instance of the TestClassA class |
2 | Created a new instance of the TestClassB class |
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:
01 | Exception in thread "main" java.lang.VerifyError: Bad type on operand stack |
04 | TestClassC.main([Ljava/lang/String;)V @9: invokestatic |
06 | Type 'TestClassB' (current frame, stack[0]) is not assignable to 'TestClassA' |
10 | locals: { '[Ljava/lang/String;', 'TestClassB' } |
11 | stack: { 'TestClassB' } |
13 | 0x0000000: bb00 0359 b700 044c 2bb8 0005 b1 |
15 | at java.lang.Class.getDeclaredMethods0(Native Method) |
16 | at java.lang.Class.privateGetDeclaredMethods(Class.java:2688) |
17 | at java.lang.Class.privateGetMethodRecursive(Class.java:3035) |
18 | at java.lang.Class.getMethod0(Class.java:3005) |
19 | at java.lang.Class.getMethod(Class.java:1771) |
20 | at sun.launcher.LauncherHelper.validateMainClass(LauncherHelper.java:544) |
21 | 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.