为了更好地理解Java中的工作原理,我想知道是否可以在运行时将目录动态添加到类路径中。
例如,如果我使用“java -jar mycp.jar”启动 .jar 并输出 java.class.path 财产,我可能会得到:
java.class.path: '.:/Library/Java/Extensions:/System/Library/Java/Extensions:/usr/lib/java'
现在可以在运行时修改此类路径以添加另一个目录吗? (例如在使用位于我要添加的目录中的 .jar 对类进行第一次调用之前)。
答案 0 :(得分:44)
您可以使用以下方法:
URLClassLoader.addURL(URL url)
但是你需要用反射做这个,因为方法是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});
}
请参阅Reflection上的Java Trail。特别是反思的缺点
部分答案 1 :(得分:22)
2014年更新:这是来自2011年Jonathan Spooner接受的答案中的代码,稍作重写,让Eclipse的验证器不再创建警告(弃用,原型)
//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()});
}
答案 2 :(得分:10)
是的,您可以使用URLClassLoader
..请参阅示例here。不使用反射。
- 编辑 -
按建议从链接中复制示例。
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);
}
}
}