如何在Java中更改CLASSPATH?

如何从Java进程中更改Java进程的CLASSPATH?


在你问我“你为什么要这么做?”之前 我马上解释一下。

当你运行一个Clojure REPL时,通常需要在你的CLASSPATH中加载更多的jar文件来加载一个Clojure源文件,而且我想这样做,而不必重新启动Clojure本身(当在Slime上使用它时不是一个真正的select在Emacs上)。

这就是原因,但我不希望这个问题被标记为某种奇怪的语言的某些奇怪的编辑器,并被大多数可能有答案的Java开发人员所忽视。

一些一般性评论:

你不能(以保证工作的便携方式,见下文)改变系统类path。 相反,您需要定义一个新的ClassLoader。

ClassLoaders以分层的方式工作…因此,任何对X类进行静态引用的类都需要加载到与X相同的ClassLoader中,或者加载到子ClassLoader中。 您不能使用任何自定义ClassLoader来正确加载由系统ClassLoader链接加载的代码,如果以前没有这样做的话。 因此,除了您定位的额外代码外,您还需要安排主要应用程序代码在自定义ClassLoader中运行。
(这就是说, 破解 -在评论这个扩展URLClassLoader例子中都提到)

你可能会考虑不写自己的ClassLoader,而只是使用URLClassLoader。 创build一个URL 不在父类加载器url中的URLClassLoader。

 URL[] url={new URL("file://foo")}; URLClassLoader loader = new URLClassLoader(url); 

更完整的解决scheme是:

 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,可能并不是这样),您也可以使用reflection来实际修改系统类path…(但是这是一个破解;)):

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

我不相信你可以 – 正确的做法(我相信)是用新的path创build一个新的类加载器。 或者,您可以编写自己的类加载器,它允许您dynamic地更改类path(用于该加载器)。

你可能想看看使用java.net.URLClassLoader 。 它允许你以编程方式加载最初不在你的类path中的类,尽pipe我不确定这是否正是你所需要的。

没有必要写你自己的类加载器! 有clojure.lang.DynamicClassLoader 。

http://blog.japila.pl/2011/01/dynamically-redefining-classpath-in-clojure-repl/

从下面的两个链接可以看出,VonC给出的方法似乎是最好的,但是查看一些这些post和谷歌的“Javadynamic类path”或“Javadynamic类加载”,并从那里找出一些信息。

我会更深入地发帖,但VonC已经做了很多工作。

从dynamic加载类和Jar文件 。

也检查这个太阳论坛post 。

 String s="java -classpath abcd/ "+pgmname+" "+filename; Process pro2 = Runtime.getRuntime().exec(s); BufferedReader in = new BufferedReader(new InputStreamReader(pro2.getInputStream())); 

是一个在java程序中改变类path的例子