5

I am trying to add jar file to classpath at runtime. I use this code

 public static void addURL(URL u) throws IOException {

            URLClassLoader sysloader = (URLClassLoader) ClassLoader
                    .getSystemClassLoader();
            Class<URLClassLoader> sysclass = URLClassLoader.class;

            try {
                Method method = sysclass.getDeclaredMethod("addURL", parameters);
                method.setAccessible(true);
                method.invoke(sysloader, new Object[] { u });
                System.out.println(u);
            } catch (Throwable t) {
                t.printStackTrace();
                throw new IOException("Error");
            }

        }

System out prints this url:

file:/B:/Java/Tools/mysql-connector-java-5.1.18/mysql-connector-java-5.1.18/mysql-connector-java-5.1.18-bin.jar

I was check this path carefully, this jar exist. Even this test show that com.mysql.jdbc. Driver class exists.

javap -classpath "B:\Java\Tools\mysql-connector-java-5.1.18\
mysql-connector-java-5.1.18\mysql-connector-java-5.1.18-bin.jar" com.mysql.jdbc.
Driver
Compiled from "Driver.java"
public class com.mysql.jdbc.Driver extends com.mysql.jdbc.NonRegisteringDriver i
mplements java.sql.Driver{
    public com.mysql.jdbc.Driver()       throws java.sql.SQLException;
    static {};
}

But I still get java.lang.ClassNotFoundException when I use this Class.forName(driver). What is wrong with this code?

itun
  • 3,439
  • 12
  • 51
  • 75
  • You would like it to throw an exception? What kind of an exception? When you say "what is wrong with this code?" Please tell us more about your actual outcome and what you expect – ControlAltDel May 16 '12 at 19:10
  • possible duplicate of [Adding files to java classpath at runtime](http://stackoverflow.com/questions/1010919/adding-files-to-java-classpath-at-runtime) – NPE May 16 '12 at 19:23
  • possible duplicate of [How should I load Jars dynamically at runtime?](http://stackoverflow.com/questions/60764/how-should-i-load-jars-dynamically-at-runtime) – Nick Grealy May 22 '15 at 00:06

2 Answers2

5

The URL is ok, nevertheless you try to load a jar from classpath, so it means that yo need to have the file in cp first. In your case you want to load a jar that is not in classpath so you have to use URLClassLoader and for JAR you can use also the JARClassLoader If you want some sample lesson on it: http://docs.oracle.com/javase/tutorial/deployment/jar/jarclassloader.html

Here a sample I ran by myself see if helps you. It search the Logger class of Log4j that is not in my classpath, of course i got exception on invocation of the constructor since i did not pass the right params to the constructor

package org.stackoverflow;
import java.io.File;
import java.net.URL;
import java.net.URLClassLoader;

public class URLClassLoaderSample
{
  public static void main(String[] args) throws Exception
  {
    File f = new File("C:\\_programs\\apache\\log4j\\v1.1.16\\log4j-1.2.16.jar");
    URLClassLoader urlCl = new URLClassLoader(new URL[] { f.toURL()},System.class.getClassLoader());
    Class log4jClass = urlCl.loadClass("org.apache.log4j.Logger");
    log4jClass.newInstance();
  }
}



Exception in thread "main" java.lang.InstantiationException: org.apache.log4j.Logger
    at java.lang.Class.newInstance0(Class.java:357)
    at java.lang.Class.newInstance(Class.java:325)
    at org.stackoverflow.URLClassLoaderSample.main(URLClassLoaderSample.java:19)

Exception due to the wrong invocation, nevertheless at this stage we already found the class

miks
  • 514
  • 2
  • 5
  • I have read the tutorial. Thx. But I did not understand how it can help me to make jar file accessible for my application? "you have to use URLClassLoader" - how I should use it? I understood I should use system url class loader. The quote from URLClassLoader docs: "both JAR files and directories" – itun May 16 '12 at 20:18
  • Is it the same what I did, is not it? – itun May 16 '12 at 21:44
  • no, you used a URLClassLoader to invoke the method addURL all with reflection. I used a URLClass loader to get the class of the requested object. just use the same sample and change the url from my sample with the url you need. – miks May 16 '12 at 22:15
  • This does not work. Mb this example is working because it creates a class instance from the loaded class. But I need to load drivers which use jdbc, not my code. – itun May 16 '12 at 22:21
  • Just to understand what you are trying to do - you have a driver (for example the mysql one) that is not in you classpath and you want to load it at runtime? – miks May 17 '12 at 04:35
1

Ok try the alternative approach with DataSource and not directly the Driver Below is the code (working with oracle driver, i don't have my sql db, but the properties are the same) Generally using the DataSource interface is the preferred approach since JDBC 2.0 The DataSource jar was not in the classpath neither for the test below

public static void urlCLSample2() throws Exception
{

    File f = new File("C:\\_programs\\jdbc_drivers\\oracle\\v11.2\\ojdbc6.jar");

    URLClassLoader urlCl = new URLClassLoader(new URL[] { f.toURL() }, System.class.getClassLoader());
    // replace the data source class with MySQL data source class.
    Class dsClass = urlCl.loadClass("oracle.jdbc.pool.OracleDataSource");
    DataSource ds = (DataSource) dsClass.newInstance();

    invokeProperty(dsClass, ds, "setServerName", String.class, "<put your server here>");
    invokeProperty(dsClass, ds, "setDatabaseName", String.class, "<put your db instance here>");
    invokeProperty(dsClass, ds, "setPortNumber", int.class, <put your port here>);
    invokeProperty(dsClass, ds, "setDriverType",String.class, "thin");
    ds.getConnection("<put your username here>", "<put your username password here>");

    System.out.println("Got Connection");
  }

  // Helper method to invoke properties
  private static void invokeProperty(Class dsClass, DataSource ds, String propertyName, Class paramClass,
      Object paramValue) throws Exception
  {
    try
    {
      Method method = dsClass.getDeclaredMethod(propertyName, paramClass);
      method.setAccessible(true);
      method.invoke(ds, paramValue);
    }
    catch (Exception e)
    {
      throw new Exception("Failed to invoke method");
    }
  }
miks
  • 514
  • 2
  • 5