Wednesday, April 22, 2009

java.lang.UnsupportedClassVersionError: Bad version number in .class file

I was recently deploying a webApp in Eclipse (MyEclipse) using Tomcat when suddenly I got a UnsupportedClassVersionError:

java.lang.UnsupportedClassVersionError: Bad version number in .class file
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(Unknown Source)
at java.security.SecureClassLoader.defineClass(Unknown Source)
at org.apache.catalina.loader.WebappClassLoader.findClassInternal(WebappClassLoader.java:1817)
at org.apache.catalina.loader.WebappClassLoader.findClass(WebappClassLoader.java:872)
at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1325)
at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1204)
at org.apache.catalina.startup.WebAnnotationSet.loadClassAnnotation(WebAnnotationSet.java:145)
at org.apache.catalina.startup.WebAnnotationSet.loadApplicationListenerAnnotations(WebAnnotationSet.java:73)
at org.apache.catalina.startup.WebAnnotationSet.loadApplicationAnnotations(WebAnnotationSet.java:56)
at org.apache.catalina.startup.ContextConfig.applicationAnnotationsConfig(ContextConfig.java:297)
at org.apache.catalina.startup.ContextConfig.start(ContextConfig.java:1064)
at org.apache.catalina.startup.ContextConfig.lifecycleEvent(ContextConfig.java:261)
at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:117)
at org.apache.catalina.core.StandardContext.start(StandardContext.java:4236)
at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:791)
at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:771)
at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:525)
at org.apache.catalina.startup.HostConfig.deployDirectory(HostConfig.java:920)
at org.apache.catalina.startup.HostConfig.deployDirectories(HostConfig.java:883)
at org.apache.catalina.startup.HostConfig.deployApps(HostConfig.java:492)
at org.apache.catalina.startup.HostConfig.start(HostConfig.java:1138)
at org.apache.catalina.startup.HostConfig.lifecycleEvent(HostConfig.java:311)
at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:117)
at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1053)
at org.apache.catalina.core.StandardHost.start(StandardHost.java:719)
at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1045)
at org.apache.catalina.core.StandardEngine.start(StandardEngine.java:443)
at org.apache.catalina.core.StandardService.start(StandardService.java:516)
at org.apache.catalina.core.StandardServer.start(StandardServer.java:710)
at org.apache.catalina.startup.Catalina.start(Catalina.java:566)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:288)
at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:413)


So my initial thought was "ok, a class is not loaded, but which one???".

Well - it turns out that this information would probably have led me down the wrong path anyway... and you don't need it (so don't get frustrated with whoever created that error message!).

The problem occurs, generally, when you compile a .java file with one version of JDK and then run the (compiled) .class with a different version of the Java Virtual Machine.

So... how was I doing this? Well - the .class file is being run within Tomcat and the .java file is being compiled by the preferred java compiler set in myEclipse. Ideally, these two versions would be the same - however they can be quite different. This won't be a problem AS LONG AS the Tomcat Java version (ie the Java running the .class files) is not an older version than the Java version used to compile the .class file from .java. It turns out that I had accidently set the Tomcat Java version to be an older one than the JAVA version being used to compile the code.

In MyEclipse:

Tomcat Java Version is set by:

  • MyEclipse Tomcat[*] -> Configure -> Jdk -> Tomcat JDK Name

MyEclipse Compiler Java Version is set by:

  • Project-> Properties -> Java Compiler -> Compiler Compliance Level
  • Window -> Preferences -> Java -> Installed JREs -> Selected JRE

So, all I had to do to fix this was to set both the Tomcat JDK Name and Selected JRE to jre1.6.0_05 and compiler compliance to 1.6 and I'd fixed the problem.




[*] or whichever Tomcat you are using...