可以在运行时将目录添加到类路径吗?

为了更好地理解Java中的工作原理,我想知道我是否可以在运行时动态地将目录添加到类路径中。

例如,如果我使用“java -jar mycp.jar”启动.jar并输出java.class.path属性,我可能会得到:

java.class.path: '.:/Library/Java/Extensions:/System/Library/Java/Extensions:/usr/lib/java' 

现在可以在运行时修改此类路径以添加另一个目录吗? (例如在使用位于我要添加的目录中的.jar对类进行第一次调用之前)。

您可以使用以下方法:

 URLClassLoader.addURL(URL url) 

但是由于方法protected您需要使用reflection执行此操作:

 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}); } 

请参阅reflection Java Trail。 特别是反思的缺点

2014年更新:这是来自2011年Jonathan Spooner接受的答案中的代码,稍作重写,让Eclipse的validation器不再创建警告(弃用,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 urlClass = URLClassLoader.class; Method method = urlClass.getDeclaredMethod("addURL", new Class[]{URL.class}); method.setAccessible(true); method.invoke(urlClassLoader, new Object[]{u.toURL()}); } 

是的,您可以使用URLClassLoader ..请参阅此处的示例。 不使用reflection。

– 编辑 –

根据建议从链接复制示例。

 import javax.naming.*; import java.util.Hashtable; import java.net.URLClassLoader; import java.net.URL; import java.net.MalformedURLException; public class ChangeLoader { public static void main(String[] args) throws MalformedURLException { if (args.length != 1) { System.err.println("usage: java ChangeLoader codebase_url"); System.exit(-1); } String url = args[0]; ClassLoader prevCl = Thread.currentThread().getContextClassLoader(); // Create class loader using given codebase // Use prevCl as parent to maintain current visibility ClassLoader urlCl = URLClassLoader.newInstance(new URL[]{new URL(url)}, prevCl); try { // Save class loader so that we can restore later Thread.currentThread().setContextClassLoader(urlCl); // Expect that environment properties are in // application resource file found at "url" Context ctx = new InitialContext(); System.out.println(ctx.lookup("tutorial/report.txt")); // Close context when no longer needed ctx.close(); } catch (NamingException e) { e.printStackTrace(); } finally { // Restore Thread.currentThread().setContextClassLoader(prevCl); } } }