你如何改变Java中的CLASSPATH?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (47)

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

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

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

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

提问于
用户回答回答于

系统不再是一个。java.lang.ClassLoaderjava.net.URLClassLoader

请参阅“ Java 9迁移指南:七个最常见的挑战

我刚刚描述的类加载策略是以新类型实现的,在Java 9中,应用程序类加载器是这种类型的。 这意味着它URLClassLoader不再是一个了,所以偶尔(URLClassLoader) getClass().getClassLoader()(URLClassLoader) ClassLoader.getSystemClassLoader()序列将不再执行。

java.lang.ModuleLayer将是一种替代方法,用于影响模块路径(而不是类路径)。请参阅“ Java 9模块 - JPMS基础知识 ”。

对于Java 8或更低版本:

一些一般性评论:

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

ClassLoaders以分层方式工作...因此,任何对X类进行静态引用的类都需要加载到与X相同的ClassLoader中,或者加载到子ClassLoader中。您不能使用任何自定义ClassLoader来正确加载由系统ClassLoader链接加载的代码,如果以前没有这样做的话。因此,除了您定位的额外代码外,您还需要安排主要应用程序代码在自定义ClassLoader中运行。 你可能会考虑不写你自己的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,可能并非如此),您也可以使用反射来实际修改系统类路径...(但这是一种破解;)):

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");
用户回答回答于

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

扫码关注云+社区