You are viewing a plain text version of this content. The canonical link for it is here.
Posted to derby-dev@db.apache.org by Andrew McIntyre <mc...@gmail.com> on 2006/08/01 03:01:12 UTC

ij gets UnsupportedClassVersionError with JDK 1.3.1 (DERBY-1609)

A recent change to ij.java added the following line:

+		  ijE = new org.apache.derby.impl.tools.ij.Main14(false);

Apparently the default classloader, when it sees that this class may
be instantiated, will attempt to load this class. On JDK 1.3.1, this
leads to an UnsupportedClassVersionError being thrown, since Main14 is
compiled with "-target 1.4". The solution is probably to load the
class via reflection. At the end of this mail is a proposed solution,
but I'm sure it could be improved. I simply catch and report any of
the exceptions that are thrown by the reflection methods. We're
unlikely to hit any of them, and throwing them seemed like quite a
burden for a public API, but maybe there's a better way to handle all
these. I also haven't tried this with the security manager yet.

Any comments greatly appreciated. If anyone feels this requires a JIRA
to fix, let me know, otherwise, it might be considered a part of
DERBY-1609.

Thanks,
andrew


Index: java/tools/org/apache/derby/tools/ij.java
===================================================================
--- java/tools/org/apache/derby/tools/ij.java	(revision 427381)
+++ java/tools/org/apache/derby/tools/ij.java	(working copy)
@@ -32,6 +32,10 @@
 import java.io.InputStream;
 import java.io.PrintStream;
 import java.io.UnsupportedEncodingException;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+
 import java.sql.Connection;
 import java.util.Properties;

@@ -98,14 +102,33 @@
 		          LocalizedResource.getInstance().
                     getNewEncodedOutput(sqlOut, outputEncoding);

-	  Main ijE;
+	  Main ijE = null;
 	  if (JVMInfo.JDK_ID == JVMInfo.J2SE_13)
 	  {
 		  ijE = new Main(false);
 	  }
 	  else
 	  {
-		  ijE = new org.apache.derby.impl.tools.ij.Main14(false);
+                  /* instantiate Main14 via reflection. In JDK 1.3.1, the
+                   * VM will attempt to load the class when it sees the
+                   * invokespecial instruction with the constuctor for Main14,
+                   * which would cause an UnsupportedClassVersion to be thrown.
+                   */
+                  try {
+                      Class ijC =
Class.forName("org.apache.derby.impl.tools.ij.Main14");
+                      Constructor ijCconstruct =
ijC.getConstructor(new Class [] { boolean.class });
+		      ijE = (Main)ijCconstruct.newInstance( new Object[] { new
Boolean(false) });
+                  } catch (ClassNotFoundException cnfe) {
+                      cnfe.printStackTrace();
+                  } catch (NoSuchMethodException nsme) {
+                      nsme.printStackTrace();
+                  } catch (InstantiationException ie) {
+                      ie.printStackTrace();
+                  } catch (IllegalAccessException iae) {
+                      iae.printStackTrace();
+                  } catch (InvocationTargetException ite) {
+                      ite.printStackTrace();
+                  }
 	  }	
 	
 	  LocalizedInput li = LocalizedResource.getInstance().

Re: ij gets UnsupportedClassVersionError with JDK 1.3.1 (DERBY-1609)

Posted by Daniel John Debrunner <dj...@apache.org>.
Andrew McIntyre wrote:
> A recent change to ij.java added the following line:
> 
> +          ijE = new org.apache.derby.impl.tools.ij.Main14(false);
> 
> Apparently the default classloader, when it sees that this class may
> be instantiated, will attempt to load this class. On JDK 1.3.1, this
> leads to an UnsupportedClassVersionError being thrown, since Main14 is
> compiled with "-target 1.4". The solution is probably to load the
> class via reflection. At the end of this mail is a proposed solution,
> but I'm sure it could be improved. I simply catch and report any of
> the exceptions that are thrown by the reflection methods. We're
> unlikely to hit any of them, and throwing them seemed like quite a
> burden for a public API, but maybe there's a better way to handle all
> these. I also haven't tried this with the security manager yet.

Interesting, the  ij class already had this code:

	  /* We decide which verion of ij (2.0 or 4.0) to
	   * load based on the same criteria that the JDBC driver
	   * uses.
	   */
	  if (JVMInfo.JDK_ID == JVMInfo.J2SE_13)
	  {
		  Main.main(args);
	  }
	  else
	  {
		  org.apache.derby.impl.tools.ij.Main14.main(args);
	  }

So I'd assumed since it was loading Main14, then my new code would be ok
as well.

Dan.


Re: ij gets UnsupportedClassVersionError with JDK 1.3.1 (DERBY-1609)

Posted by Daniel John Debrunner <dj...@apache.org>.
Andrew McIntyre wrote:

> A recent change to ij.java added the following line:
> 
> +          ijE = new org.apache.derby.impl.tools.ij.Main14(false);
> 
> Apparently the default classloader, when it sees that this class may
> be instantiated, will attempt to load this class. On JDK 1.3.1, this
> leads to an UnsupportedClassVersionError being thrown, since Main14 is
> compiled with "-target 1.4". The solution is probably to load the
> class via reflection. At the end of this mail is a proposed solution,
> but I'm sure it could be improved. I simply catch and report any of
> the exceptions that are thrown by the reflection methods. We're
> unlikely to hit any of them, and throwing them seemed like quite a
> burden for a public API, but maybe there's a better way to handle all
> these. I also haven't tried this with the security manager yet.
> 
> Any comments greatly appreciated. If anyone feels this requires a JIRA
> to fix, let me know, otherwise, it might be considered a part of
> DERBY-1609.

I've put in a temp fix and will work on a real fix as part of
DERBY-1609. I assume this is the same reason as to why the "mt" test
code always loads the utilMain class, even in a jdk 1.4 environment. I
almost thought about changing that to use utilMain14, glad I didn't now!

Dan.