Most common error : java.lang.UnsupportedClassVersionError: when is it thrown by a JVM & how to resolve it | Experinced level java interview question

UnsupportedClassVersionError is (evidently a descendant of the Error class in Java) which subclasses java.lang.ClassFormatError which in turn subclasses java.lang.LinkageError (which is a direct subclass of java.lang.Error). This error is thrown in the cases when the JVM (Java Virtual Machine) attempts to read a class file and finds that the major and minor version numbers in the particular class file are not supported. This happens in the cases when a higher version of Java Compiler is used to generate the class file than the JVM version which is used to execute that class file. Please do notice that this is not true vice-versa which means you can comfortably use a higher version of JVM to run a class file compiled using an earlier version of Java Compiler. Let’s understand why? We'll see below a valid Java program and subsequently an alert and a stack trace of the error which are thrown as a result of the above explained situation which causes UnsupportedClassVersionError. FYI: The output

public class TestFinally {

      public static void main(String[] args) {
             
            try{
                  try{
                        throw new NullPointerException ("e1");
                  }
                  finally{
                        System.out.println("e2");
                  }
            }
            catch(Exception e){
                        e.printStackTrace();
            }
      }
}



The error alert and the stack trace if the right JVM is not used



java.lang.UnsupportedClassVersionError: TestFinally (Unsupported major.minor version 49.0)
      at java.lang.ClassLoader.defineClass0(Native Method)
      at java.lang.ClassLoader.defineClass(ClassLoader.java:539)
      at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:123)
      at java.net.URLClassLoader.defineClass(URLClassLoader.java:251)
      at java.net.URLClassLoader.access$100(URLClassLoader.java:55)
      at java.net.URLClassLoader$1.run(URLClassLoader.java:194)
      at java.security.AccessController.doPrivileged(Native Method)
      at java.net.URLClassLoader.findClass(URLClassLoader.java:187)
      at java.lang.ClassLoader.loadClass(ClassLoader.java:289)
      at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:274)
      at java.lang.ClassLoader.loadClass(ClassLoader.java:235)
      at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:302)


The minor and major version numbers are represented by the major_version and minor_version items respectively in a Java Class File structure. A combination of these two unsigned integers (both of length 2 bytes each) determines the particular version of the class file format. If a class file has major version number M and minor version number m, we denote the version of its class file format as M.m.

As per Java VM Spec, “A Java virtual machine implementation can support a class file format of version v if and only if v lies in some contiguous range Mi.0 v Mj.m. Only Sun can specify what range of versions a Java virtual machine implementation conforming to a certain release level of the Java platform may support.” For example: Implementations of version 1.2 of the Java 2 platform can support class file formats of versions in the range 45.0 through 46.0 inclusive.

Major version number of the class file formats of the popular Java versions are: J2SE 6.0 = 50, J2SE 5.0 = 49, JDK 1.4 = 48, JDK 1.3 = 47, JDK 1.2 = 46, JDK 1.1 = 45. Now you understand what in our example “major.minor version 49.0” signifies? It simply means we have used J2SE 5.0 for compiling the source code as the class file format is 49.0 where major_version is ‘49’ and minor_version is ‘0’.

Errors are never detected at compile time. This is quite easier to understand in this case – how can the compiler have the information at the time of compilation about which version of JVM would be used execute the compiled class file? It can't, right? So is the case with other errors as well. This is the reason why all the Errors are unchecked. The error alert also rightly shows that it's a JVM Launcher error.

How to resolve UnsupportedClassVersionError?


Whenever you encounter this error, do check if you’re using an earlier version of JVM to execute the class file than the corresponding version of compiler you used to compile the source code. The example shown here was compiled using Java 5.0 compiler, but when I tried to run using JVM 1.4, I got the above error. I just needed to switch either to a JVM version 5.0 or above OR needed to switch to a Java Compiler of JDK 1.4 or below (you of course need to make sure the source code is compatible with the corresponding version of the compiler otherwise you’ll start getting other compiler errors).

A higher JVM version doesn’t cause a problem in most of cases unless the class file format is quite old (and hence doesn’t lie in the supported range as specified by Sun for that particular JVM version ... as discussed above). But, it’s always a good practice to have both the Compiler and the JVM of the same version.

No comments:

Post a Comment

Note: Only a member of this blog may post a comment.