Reputation: 6014
In order to better understand how things works in Java, I'd like to know if I can dynamically add, at runtime, a directory to the class path.
For example, if I launch a .jar using "java -jar mycp.jar" and output the java.class.path property, I may get:
java.class.path: '.:/Library/Java/Extensions:/System/Library/Java/Extensions:/usr/lib/java'
Now can I modify this class path at runtime to add another directory? (for example before making the first call to a class using a .jar located in that directory I want to add).
Upvotes: 38
Views: 40591
Reputation: 17476
Yes, you can use URLClassLoader
.. see example here. Doesn't use reflection.
-- edit --
Copying example from the link as suggested.
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Hashtable;
import javax.naming.*;
public class ChangeLoader {
public static void main(String[] args) throws MalformedURLException {
if (args.length != 1) {
System.err.println("usage: java ChangeLoader extra_classpath_url");
System.exit(-1);
}
String url = args[0];
// Save class loader so that we can restore later
ClassLoader prevCl = Thread.currentThread().getContextClassLoader();
// Use prevCl as parent, so we extend instead of replace
ClassLoader urlCl =
URLClassLoader.newInstance(new URL[] {new URL(url)}, prevCl);
try {
Thread.currentThread().setContextClassLoader(urlCl);
Context ctx = new InitialContext();
System.out.println(ctx.lookup("tutorial/report.txt"));
ctx.close();
} catch (NamingException e) {
e.printStackTrace();
} finally {
// Restore old loader
Thread.currentThread().setContextClassLoader(prevCl);
}
} // main()
}
Upvotes: 12
Reputation: 7752
You can use the following method:
URLClassLoader.addURL(URL url)
But you'll need to do this with reflection since the method is protected
:
public static void addPath(String s) throws Exception {
File f = new File(s);
URL u = f.toURL();
URLClassLoader urlClassLoader = (URLClassLoader) ClassLoader.getSystemClassLoader();
Class urlClass = URLClassLoader.class;
Method method = urlClass.getDeclaredMethod("addURL", new Class[]{URL.class});
method.setAccessible(true);
method.invoke(urlClassLoader, new Object[]{u});
}
See the Java Trail on Reflection. Especially the section Drawbacks of Reflection
Upvotes: 51
Reputation: 9303
Update 2014: this is the code from the accepted answer, by Jonathan Spooner from 2011, slightly rewritten to have Eclipse's validators no longer create warnings (deprecation, rawtypes)
//need to do add path to Classpath with reflection since the URLClassLoader.addURL(URL url) method is protected:
public static void addPath(String s) throws Exception {
File f = new File(s);
URI u = f.toURI();
URLClassLoader urlClassLoader = (URLClassLoader) ClassLoader.getSystemClassLoader();
Class<URLClassLoader> urlClass = URLClassLoader.class;
Method method = urlClass.getDeclaredMethod("addURL", new Class[]{URL.class});
method.setAccessible(true);
method.invoke(urlClassLoader, new Object[]{u.toURL()});
}
Upvotes: 26