0

I am trying to understand why we are getting the following exception:


java.lang.NoClassDefFoundError: java/sql/Connection

Let me start by offering some context as to what is happening. I have a set of classes that are contained within a jar file that is added to the boot class path. Now these classes have instances that are passed to them and they call methods on those instances. In a certain cases, we are calling the isClosed method for the passed java.sql.Connection instance. This instance is not part of the boot class path so is not visible to my class. I understand that if I perform a Class.forName("java.sql.Connection"); that it will not be able to find that class. This is understood but what is strange is that if I use reflection then I am able to successfully call the isClosed method. This made me wonder if I have to update the thread context class loader. Upon checking the context class loader. It contains the platform class loader that allows me to access those classes as per java 9 migration document.

Alright, this made me wonder if there is an exception that is being thrown that is then caught and a new exception is thrown instead that does not encapsulate the original exception. I enabled jvmti exception callback and printed out the different exceptions that have been raised/caught. This information did not offer anything related to the exception. That was the only exception thrown that was related to that stack trace. It seems like this is something that the hotspot is throwing and is not generated by the java layer.

I have then tried to add the Add-Exports attribute to the manifest with the following settings java.logging/java.util.logging=ALL-UNNAMED java.sql/java.sql=ALL-UNNAMED java.xml/java.xml=ALL-UNNAMED java.xml/org.xml=ALL-UNNAMED java.xml/org.w3c=ALL-UNNAMED but that did not help.

I've even cloned the jdk 9 sources and was not able to find any clue as to how to debug this issue.

By the way, I tried to enable the debug but alas there is a bug in the jdwp agent that causes the application to crash so I can not even use the debugger to help me determine what is happening.

Any ideas, suggestions or clues would be greatly appreciated since I have run out of ideas on how to solve this issue.

Note this issue is only apparent when using java 9. Our jar file is generated using java 5 since we support java 5 or greater.

Alan Bateman
  • 5,283
  • 1
  • 20
  • 25
Claudio Corsi
  • 329
  • 1
  • 4
  • The java.sql module is mapped to the platform class loader in JDK 9 or newer. This should have no impact on regular applications but you seem to be deploying on the boot class path (with -Xbootclasspath/a I assume). Is there any reason why your JAR file is not on the class path? – Alan Bateman Mar 15 '18 at 18:20
  • This is part of our agent and it is implicitly added to the boot class path by the agent which is a native library. – Claudio Corsi Mar 15 '18 at 18:34
  • There's no guarantee that all platform classes are visible to the boot class loader. In JDK 9, there was a lot of effort put into moving the non-core modules away from the boot loader - you'll find more about this in the JDK 9 releases notes and in JEP 261. See also the section titled "Loading agent classes and the modules/classes available to the agent class" in the java.lang.instrument package description as it may be useful. – Alan Bateman Mar 15 '18 at 19:13
  • @AlanBateman I found the issue, We are using the jvmti AddModuleOpen method to include us but we are not doing that for this particular module and that is the reason that the exception is being raised. Thanks for the help. – Claudio Corsi Mar 16 '18 at 01:21
  • The JVM TI AddModuleOpen function is to open a package to another module. It doesn't change visibility, code defined to the boot loader cannot have static references to java.sql or other classes defined to the platform class loader. – Alan Bateman Mar 16 '18 at 07:08
  • Your question text is very confusing. You are talking about classes you have added to the bootstrap class path, then saying that instances of these classes are “not part of the boot class path”. That does not make any sense. Followed by “I understand that if I perform a `Class.forName("java.sql.Connection");` that it will not be able to find that class.”…What?! You understand that? Then what is your question? Then you are talking about the thread context class loader. The thread context class loader is entirely irrelevant to what you have described so far. – Holger Mar 16 '18 at 08:11

0 Answers0