2

I am trying to use multiple Oralce JDBC drivers to connect to 2 Oracle databases by followed the instruction from this Question.

I have ojdbc6.jar in the classpath of the default ClassLoader to connect to Oracle 11g.

enter image description here

To connect to another database, Oracle 8i, I wrote a code as follows

File driverJar = new File("D:/workspace/ccbs/lib/classes12.jar");
String driverClassName = "oracle.jdbc.OracleDriver";
String con = "jdbc:oracle:thin:@db1host:5555:db1";
URL[] classpath = new URL[] {driverJar.toURI().toURL()};
URLClassLoader driverLoader = new URLClassLoader(classpath, ClassLoader.getSystemClassLoader());
Class driverClass = driverLoader.loadClass(driverClassName);
System.out.println(driverClass.getProtectionDomain().getCodeSource().getLocation());

In the last line, the location of the driver class is printed. Running the program and I got

file:/D:/workspace/ccbs/lib/oravl01/oracle/11.2.0.2/jdbc/lib/ojdbc6.jar

When I remove the ojdbc6.jar from the classpath and run the program again, I got

file:/D:/workspace/ccbs/lib/classes12.jar

Please suggest why my custom URLClassLoader load the oracle.jdbc.OracleDriver from ojdbc6.jar in the default classpath instead of classes12.jar in the custom classpath.

Community
  • 1
  • 1
asinkxcoswt
  • 2,252
  • 5
  • 29
  • 57

2 Answers2

2

The answer is the class loader delegation model. ClassLoader documentation describes it.

To resolve your issue try to just replace

URLClassLoader driverLoader = new URLClassLoader(classpath, ClassLoader.getSystemClassLoader());

with

URLClassLoader driverLoader = new URLClassLoader(classpath, null);

This way you make sure that URLClassLoader doesn't use the application class path.

Stanislav Lukyanov
  • 2,147
  • 10
  • 20
1

I have made some debugging on your code and indeed it occurs. Apparently the parent class loader precedes your class loading in order and still loads the other ojdbc jar that he finds on the classpath

This thread outlines solutions to create your own custom parent-last classloader: How do I create a parent-last / child-first ClassLoader in Java, or How to override an old Xerces version that was already loaded in the parent CL?

I have tried the accepted solution of this thread, and it seems to work as expected; loads the jar defined in the driverJar variable. Only the following two lines of your code needs to be changed by utilizing ParentLastURLClassLoader

ParentLastURLClassLoader driverLoader  = new ParentLastURLClassLoader(Arrays.asList(classpath));
Class driverClass = driverLoader.loadClass(driverClassName);
Community
  • 1
  • 1
hammerfest
  • 2,203
  • 1
  • 20
  • 43
  • 2
    Messing with the class loader delegation is tricky and error-prone. This is possible but I'd recommend to use it as the last resort only. – Stanislav Lukyanov Oct 30 '16 at 17:02