如何从Java进程中更改Java进程的CLASSPATH?
在你问我之前“你为什么要这样做?”我马上解释一下。
当你运行Clojure REPL时,通常需要在CLASSPATH中加入更多的jar来加载Clojure源文件,而且我想这样做而不必重新启动Clojure本身(这不是真的在Emacs上的Slime上使用它时的一个选项。
这就是原因,但我不希望这个问题被标记为某种怪异语言的奇怪编辑器,并且被大多数可能有答案的Java开发人员所忽视。
答案 0 :(得分:78)
2017年第4季度更新:commented下方的vda8888,在Java 9中,系统java.lang.ClassLoader
不再是java.net.URLClassLoader
。
请参阅“Java 9 Migration Guide: The Seven Most Common Challenges”
我刚才描述的类加载策略是在新类型中实现的,在Java 9中,应用程序类加载器属于该类型。
这意味着它不再是URLClassLoader
,因此偶尔的(URLClassLoader) getClass().getClassLoader()
或(URLClassLoader) ClassLoader.getSystemClassLoader()
序列将不再执行。
java.lang.ModuleLayer将是一种替代方法,用于影响模块路径(而不是类路径)。例如,请参阅“Java 9 modules - JPMS basics”。
对于Java 8或更低版本:
一些一般性意见:
你不能(以可移植的方式保证工作,见下文)改变系统类路径。相反,您需要定义一个新的ClassLoader。
ClassLoaders以分层方式工作...因此,任何对X类进行静态引用的类都需要在与X相同的ClassLoader中加载,或者在子类ClassLoader中加载。您不能使用任何自定义ClassLoader来正确地使系统ClassLoader链接加载代码,如果它之前没有这样做的话。因此,除了您找到的额外代码外,您还需要安排在自定义ClassLoader中运行主应用程序代码。
(尽管如此,cracked-all在评论中提到了这个extending the URLClassLoader
)
您可能会考虑不编写自己的ClassLoader,而只是使用URLClassLoader。使用父类加载器URL中不的URL创建URLClassLoader。
URL[] url={new URL("file://foo")};
URLClassLoader loader = new URLClassLoader(url);
ClassLoader currentThreadClassLoader
= Thread.currentThread().getContextClassLoader();
// Add the conf dir to the classpath
// Chain the current thread classloader
URLClassLoader urlClassLoader
= new URLClassLoader(new URL[]{new File("mtFile").toURL()},
currentThreadClassLoader);
// Replace the thread classloader - assumes
// you have permissions to do so
Thread.currentThread().setContextClassLoader(urlClassLoader);
如果您假设JVMs系统类加载器是URLClassLoader(对于所有JVM可能都不是这样),您也可以使用反射来实际修改系统类路径...(但这是一个黑客;)):( / p>
public void addURL(URL url) throws Exception {
URLClassLoader classLoader
= (URLClassLoader) ClassLoader.getSystemClassLoader();
Class clazz= URLClassLoader.class;
// Use reflection
Method method= clazz.getDeclaredMethod("addURL", new Class[] { URL.class });
method.setAccessible(true);
method.invoke(classLoader, new Object[] { url });
}
addURL(new File("conf").toURL());
// This should work now!
Thread.currentThread().getContextClassLoader().getResourceAsStream("context.xml");
答案 1 :(得分:3)
我不相信你可以 - 正确的事情(我相信)是用新路径创建一个新的类加载器。或者,您可以编写自己的类加载器,它允许您动态更改类路径(针对该加载器)。
答案 2 :(得分:2)
没有必要编写自己的类加载器!有clojure.lang.DynamicClassLoader。
http://blog.japila.pl/2011/01/dynamically-redefining-classpath-in-clojure-repl/
答案 3 :(得分:1)
您可能需要考虑使用java.net.URLClassLoader。它允许您以编程方式加载最初不在类路径中的类,但我不确定这是否正是您所需要的。
答案 4 :(得分:1)
从下面的两个链接可以看出,VonC给出的方法似乎是最好的,但查看其中的一些帖子和google的“Java Dynamic Classpath”或“Java Dynamic Class Loading”并找出一些信息从那里。
我会更深入地发帖,但VonC已经完成了这项工作。
来自Dynamic loading of class and Jar files。
同时检查此sun forum post。
答案 5 :(得分:-3)
String s="java -classpath abcd/ "+pgmname+" "+filename;
Process pro2 = Runtime.getRuntime().exec(s);
BufferedReader in = new BufferedReader(new InputStreamReader(pro2.getInputStream()));
是在java程序中更改类路径的示例