如何在Java进程中更改Java进程的CLASSPATH?
在你问我“你为什么要这么做?”我很快就会解释它。
当您运行Clojure REPL时,通常需要在您的CLASSPATH中使用更多的jars来加载Clojure源文件,我希望不必重启Clojure本身(在Emacs上的Slime上使用它时,这并不是一个真正的选择)。
这就是原因,但我不希望这个问题被标记为某种奇怪的语言某种奇怪的编辑器,并被大多数可能有答案的Java开发人员忽视。
发布于 2008-10-31 09:37:35
Update Q4 2017: as commented by vda8888,在Java9中,系统java.lang.ClassLoader
不再是java.net.URLClassLoader
。
参见"Java 9 Migration Guide: The Seven Most Common Challenges“
,我刚刚描述的类加载策略是在一种新类型中实现的,在Java9中,应用程序类加载器就是这种类型。
这意味着它不再是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);
如果您假设JVM系统类加载器是一个URLClassLoader (并不是所有JVM都是这样),那么您也可以使用反射来实际修改系统类路径...(但这是一个黑客;)):
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");
发布于 2008-10-31 08:49:32
我不相信你可以-正确的事情(我相信)是用新的路径创建一个新的类加载器。或者,您可以编写自己的类加载器,它允许您动态地更改类路径(用于该加载器)。
发布于 2011-07-20 19:57:47
https://stackoverflow.com/questions/252893
复制相似问题