UnsupportedClassVersionError – huh?!

I was recently doing some testing with the new SQL Server 2005 v2.0 JDBC driver and couldn’t get the code to run.  Now, as anybody who does Java development in a text editor like myself knows, it is pretty easy to get the wrong CLASSPATH going if you occasionally work with different JDBC driver versions. 

So, I immediately checked my CLASSPATH, figuring I had a typo somewhere in there.  However, I was surprised to find that it was correct.  So why the heck was I getting a CLASSPATH error?  Then, I looked closer at the error and realized it was not ClassNotFoundException, but instead was UnsupportedClassVersionError.  What the heck?  I have been supporting JDBC for more than four year now and I didn’t recall every seeing that before!  So, I started looking at what had changed on my machine. 

After poking around a little, I remembered I had just rebuilt my machine a few weeks back.  However, I didn’t remember installing a JVM.  Yet, somehow I was able to run Java and Javac, so that meant some application had installed the JDK.  But what version was installed?

A quick jump out to a command prompt and a “javac –version” showed that I was running the 1.4 version of the JDK.  1.4?!  That version of the JVM is not supported by the 2.0 JDBC driver!

Just to confirm my suspicions, I wired up a quick batch file and ran some of my stock Java connectivity test code:

Here’s the batch file:

 @echo off 

echo Confirm we have the ClassPath set to the 2.0 driver
Set CLASSPATH=.;C:\JDBC\sqljdbc_2.0\enu\sqljdbc.jar
set classpath 

echo.
echo.
echo Confirm we have the 1.5 JDK
C:\j2sdk1.5\bin\java -version 

echo.
echo.
echo Compile and run the sample code with 1.5
C:\j2sdk1.5\bin\javac MSversion.java
C:\j2sdk1.5\bin\java MSversion 

echo.
echo.
echo Confirm we have the 1.4 JDK
C:\j2sdk1.4.2_19\bin\java -version 

echo.
echo.
echo Now, compile and run the sample code with 1.4
C:\j2sdk1.4.2_19\bin\javac MSversion.java
C:\j2sdk1.4.2_19\bin\java MSversion

and here’s the Java code:

 import java.*;
import java.sql.*;
import java.util.*;
import java.text.*;

class MSversion
{
    public static void main(String[] args) throws Exception
    {
        // Load the JDBC driver
        Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
        // Connect to SQL Server
        Connection conn = null;
        String url = "jdbc:sqlserver://myserver;DatabaseName=master;";

        // Process the command line input
        if (args.length == 0)
        {
            //  Connect with default id/password
            conn = DriverManager.getConnection(url, "username", "password");
            //conn = DriverManager.getConnection(url);
        }
        else if (args.length == 2)
        {
            // Connect with user-provided username and password
            String userName = args[0];
            String password = args[1];
            conn = DriverManager.getConnection(url, userName, password);
        }
        else if (args.length == 3)
        {
            // Connect with user-provided username and password and url
            String userName = args[0];
            String password = args[1];
            url= args[2];
            conn = DriverManager.getConnection(url, userName, password);
        }
        else
        {
            // Invalid command -> throw an exception
            throw new Exception("\nUsage: java version [userName password]\n");
        }

        // Driver information
        DatabaseMetaData dm = conn.getMetaData();
        System.out.println("Connected to " + dm.getURL());
        System.out.println("Driver Information");
        System.out.println("\tDriver Name:    " + dm.getDriverName());
        System.out.println("\tDriver Version: " + dm.getDriverVersion());
        System.out.println("\tDatabase Major Version: " + dm.getDatabaseMajorVersion());
        System.out.println("\tDatabase Minor Version: " + dm.getDatabaseMinorVersion());
        System.out.println();

        // Cleanup
        dm=null;
        conn.close();
        conn=null;
    }
}

Lastly, here’s the output:

 Confirm we have the ClassPath set to the 2.0 driver
CLASSPATH=.;C:\JDBC\sqljdbc_2.0\enu\sqljdbc.jar 

Confirm we have the 1.5 JDK
java version "1.5.0_19"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_19-b02)
Java HotSpot(TM) 64-Bit Server VM (build 1.5.0_19-b02, mixed mode) 

Compile and run the sample code with 1.5
Connected to jdbc:sqlserver://myserver:1433;xopenStates=false;trustServerCertificate=false;
sendStringParametersAsUnicode=true;selectMethod=direct;responseBuffering=adaptive;
packetSize=8000;loginTimeout=15;lockTimeout=-1;lastUpdateCount=true;encrypt=false;
disableStatementPooling=true;databaseName=master;applicationName=Microsoft SQL Server JDBC Driver;
Driver Information
    Driver Name:    Microsoft SQL Server JDBC Driver 2.0
    Driver Version: 2.0.1803.100
    Database Major Version: 9
    Database Minor Version: 0 

Confirm we have the 1.4 JDK
java version "1.4.2_19"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.2_19-b04)
Java HotSpot(TM) Client VM (build 1.4.2_19-b04, mixed mode) 

Now, compile and run the sample code with 1.4
java.lang.UnsupportedClassVersionError: com/microsoft/sqlserver/jdbc/SQLServerDriver 
(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)
    at java.lang.Class.forName0(Native Method)
    at java.lang.Class.forName(Class.java:141)
    at MSversion.main(MSversion.java:11)
Exception in thread "main" 

At this point, I knew all I had to do was point my PATH to either the 1.5 or 1.6 JDK and I should be fine.