如何在Java中更改类路径?

如何在Java中更改类路径?,java,clojure,classpath,Java,Clojure,Classpath,如何从Java进程内部更改Java进程的类路径 在你问我“你为什么要这么做?”之前,我会很快解释 当运行Clojure REPL时,在类路径中通常需要更多JAR来加载源文件,我希望这样做而不必重新启动Clojure本身(在Emacs上的Slime上使用Clojure时,这实际上不是一个选项) 这就是原因,但我不希望这个问题被标记为某种奇怪的语言,某种奇怪的编辑器,而被大多数可能有答案的Java开发人员忽视。我不相信你能做到-正确的做法(我相信)是用新的路径创建一个新的类加载器。或者,您可以编写

如何从Java进程内部更改Java进程的类路径


在你问我“你为什么要这么做?”之前,我会很快解释

当运行Clojure REPL时,在类路径中通常需要更多JAR来加载源文件,我希望这样做而不必重新启动Clojure本身(在Emacs上的Slime上使用Clojure时,这实际上不是一个选项)


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

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

您可能需要研究如何使用。它允许您以编程方式加载最初不在类路径中的类,尽管我不确定这是否正是您所需要的。

更新2017年第4季度:如下所示,在Java 9中,系统不再是一个应用程序

见“

我刚才描述的类装入策略是在一种新类型中实现的,在Java 9中,应用程序类装入器就是这种类型。
这意味着它不再是
URLClassLoader
,因此偶尔出现的
(URLClassLoader)getClass().getClassLoader()或
(URLClassLoader)ClassLoader.getSystemClassLoader()
序列将不再执行

将是一种替代方法,用于影响modulepath(而不是类路径)。例如见“”


对于Java 8或以下版本:

一些一般性意见:

您不能(以保证工作的可移植方式,见下文)更改系统类路径。相反,您需要定义一个新的类加载器

类装入器以分层方式工作。。。因此,对类X进行静态引用的任何类都需要加载到与X相同的类加载器中,或者加载到子类加载器中。您不能使用任何自定义类加载器使系统类加载器链接正确加载代码,如果它以前不这样做的话。因此,除了找到的额外代码外,还需要安排在自定义类加载器中运行主应用程序代码。
(尽管如此,评论中提到了该示例)

您可能会考虑不编写自己的ClassLoader,而只需使用URLCaseLoad。使用不在父类加载器url中的url创建url类加载器

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

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都是这样),那么您也可以使用反射来实际修改系统类路径。。。(但那是一种恶作剧;):


从下面的两个链接可以看出,VonC提供的方法似乎是最好的,但请查看其中的一些帖子和google的“Java动态类路径”或“Java动态类加载”,并从中找到一些信息

我会发布更深入的内容,但VonC已经完成了大部分工作


也请检查此项。

无需编写自己的类加载器!有一个


是java程序中类路径的一个例子

在Linux上使用java 1.6.0_13(64位)时,“更完整”的解决方案不适用于我。另一方面,addURL方法按预期工作。这可以用于添加jar。但是有没有一种方法可以移除一个罐子呢?例如,我需要用一个新版本更新一个jar。@dmarrazzo 6年以上,我不知道。试着问一个单独的问题。我在另一个线程中遇到了这个解决方案,但根据你的解释,我清楚地知道如何使用它。1+第二个解决方案(假设JVMs系统类加载器是URLClassLoader)停止在JRE 9中工作。系统类加载器不再是URL类加载器。类路径只为子java进程而更改,而不是为代码运行的环境而更改。这有点创造性,但对大多数人来说是无用的。这是一个用新类路径启动新Java进程的例子。这不是一个改变任何事情的例子。
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");
String s="java  -classpath abcd/ "+pgmname+" "+filename;   
Process pro2 = Runtime.getRuntime().exec(s); 
BufferedReader in = new BufferedReader(new InputStreamReader(pro2.getInputStream()));