Tuesday, April 2, 2013

java.lang.UnsupportedClassVersionError

When running an application named StoreFrontService, we have run into this exception:
  • java.lang.UnsupportedClassVersionError
In this article, we will examine what it is and how to resolve it.

Class Loading Phases


There are three phases in class loading[1]:
  • Loading
    • See below
  • Linking
    • Bytecode verification[6]
      • Checks the classfile semantics, checks the constant pool symbols, and does type checking
    • Preparation
      • Creates and initializes static fields to standard defaults and allocates method tables
  • Initializing
    •  Runs the class static initializers, and initializers for static fields
For a given Java class or Java interface, the load class phase takes its name, finds the binary in Java classfile format, defines the Java class, and creates a java.lang.Class object to represent that given Java class or Java interface.
The load class phase can throw a NoClassDefFound error if a binary representation of a Java class or Java interface cannot be found. In addition, the load class phase does format checking on the syntax of the classfile, which can throw a ClassFormatError or UnsupportedClassVersionError.

The Exception


In our expriement, we have seen the following exception being thrown:

####<Mar 21, 2013 8:16:43 AM PDT> <Error> <Class Loaders> <sfperf-x6250-10> <MS_1> <[ACTIVE] ExecuteThread: '8' for queue: 'weblogic.kernel.Default (self-tuning)'> <<WLS Kernel>> <> <> <1363879003661> <BEA-2162500> <Class, oracle.fodemo.storefront.store.service.server.serviceinterface.StoreFrontServiceImpl, was compiled with an incompatible version of Java. Make sure that all the classes needed by the application have been compiled with a compatible java version. java.lang.UnsupportedClassVersionError: oracle/fodemo/storefront/store/service/server/serviceinterface/StoreFrontServiceImpl : unsupported classversion 51.0
java.lang.UnsupportedClassVersionError: oracle/fodemo/storefront/store/service/server/serviceinterface/StoreFrontServiceImpl : unsupported classversion 51.0
        at java.lang.ClassLoader.defineClass1(Native Method)
        at java.lang.ClassLoader.defineClassCond(ClassLoader.java:631)
        at java.lang.ClassLoader.defineClass(ClassLoader.java:615)
        at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:14

      
This turns out to be that our application StoreFrontService was compiled in JDK 7 (class version: 51)[7] and we were running it on JRockit bundled with Java 1.6 VM (class version: 50). The compiler is not backwards compatible[2] because bytecode generated with JDK 7 won't run in Java 1.6 VM (unless compiled with the -target 1.6 flag[3]). But the JVM is backwards compatible, as it can run older bytecodes.

References

  1. Java Performance by Charlie Hunt, Binu John, David Dagastine 
  2. Is JDK “upward” or “backward” compatible?
  3. Cross-Compilation Options
  4. Java SE 6 vs. JRE 1.6 vs. JDK 1.6 - What do these mean?
  5. JRockit Version Information
  6. Java Virtual Machine Specification
  7. Unsupported major.minor version 51.0

No comments: