可以在运行时将目录添加到类路径中吗?

发布于 2024-12-11 20:45:36 字数 355 浏览 0 评论 0原文

为了更好地理解 Java 中的工作原理,我想知道是否可以在运行时动态地将目录添加到类路径中。

例如,如果我使用 "java -jar mycp.jar" 启动 .jar 并输出 java.class.path 属性,则我可能会得到:

java.class.path: '.:/Library/Java/Extensions:/System/Library/Java/Extensions:/usr/lib/java'

现在我可以在运行时修改这个类路径来添加另一个目录吗? (例如,在使用位于我要添加的目录中的 .jar 第一次调用类之前)。

In order to better understand how things works in Java, I'd like to know if I can dynamically add, at runtime, a directory to the class path.

For example, if I launch a .jar using "java -jar mycp.jar" and output the java.class.path property, I may get:

java.class.path: '.:/Library/Java/Extensions:/System/Library/Java/Extensions:/usr/lib/java'

Now can I modify this class path at runtime to add another directory? (for example before making the first call to a class using a .jar located in that directory I want to add).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

风蛊 2024-12-18 20:45:36

您可以使用以下方法:

URLClassLoader.addURL(URL url)

但是您需要通过反射来执行此操作,因为该方法是受保护的:

public static void addPath(String s) throws Exception {
    File f = new File(s);
    URL u = f.toURL();
    URLClassLoader urlClassLoader = (URLClassLoader) ClassLoader.getSystemClassLoader();
    Class urlClass = URLClassLoader.class;
    Method method = urlClass.getDeclaredMethod("addURL", new Class[]{URL.class});
    method.setAccessible(true);
    method.invoke(urlClassLoader, new Object[]{u});
}

请参阅 反射。特别是反射的缺点部分

You can use the following method:

URLClassLoader.addURL(URL url)

But you'll need to do this with reflection since the method is protected:

public static void addPath(String s) throws Exception {
    File f = new File(s);
    URL u = f.toURL();
    URLClassLoader urlClassLoader = (URLClassLoader) ClassLoader.getSystemClassLoader();
    Class urlClass = URLClassLoader.class;
    Method method = urlClass.getDeclaredMethod("addURL", new Class[]{URL.class});
    method.setAccessible(true);
    method.invoke(urlClassLoader, new Object[]{u});
}

See the Java Trail on Reflection. Especially the section Drawbacks of Reflection

夏有森光若流苏 2024-12-18 20:45:36

2014 年更新:这是来自 Jonathan Spooner 2011 年接受的答案中的代码,稍作重写以使 Eclipse 的验证器不再创建警告(弃用、原始类型)

//need to do add path to Classpath with reflection since the URLClassLoader.addURL(URL url) method is protected:
public static void addPath(String s) throws Exception {
    File f = new File(s);
    URI u = f.toURI();
    URLClassLoader urlClassLoader = (URLClassLoader) ClassLoader.getSystemClassLoader();
    Class<URLClassLoader> urlClass = URLClassLoader.class;
    Method method = urlClass.getDeclaredMethod("addURL", new Class[]{URL.class});
    method.setAccessible(true);
    method.invoke(urlClassLoader, new Object[]{u.toURL()});
}

Update 2014: this is the code from the accepted answer, by Jonathan Spooner from 2011, slightly rewritten to have Eclipse's validators no longer create warnings (deprecation, rawtypes)

//need to do add path to Classpath with reflection since the URLClassLoader.addURL(URL url) method is protected:
public static void addPath(String s) throws Exception {
    File f = new File(s);
    URI u = f.toURI();
    URLClassLoader urlClassLoader = (URLClassLoader) ClassLoader.getSystemClassLoader();
    Class<URLClassLoader> urlClass = URLClassLoader.class;
    Method method = urlClass.getDeclaredMethod("addURL", new Class[]{URL.class});
    method.setAccessible(true);
    method.invoke(urlClassLoader, new Object[]{u.toURL()});
}
海的爱人是光 2024-12-18 20:45:36

是的,您可以使用 URLClassLoader.. 请参阅示例 这里。不使用反射。

-- 编辑 --

按照建议从链接复制示例。

import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Hashtable;
import javax.naming.*;

public class ChangeLoader {
  public static void main(String[] args) throws MalformedURLException {
    if (args.length != 1) {
      System.err.println("usage: java ChangeLoader extra_classpath_url");
      System.exit(-1);
    }

    String url = args[0];
    // Save class loader so that we can restore later
    ClassLoader prevCl = Thread.currentThread().getContextClassLoader();

    // Use prevCl as parent, so we extend instead of replace
    ClassLoader urlCl = 
          URLClassLoader.newInstance(new URL[] {new URL(url)}, prevCl);

    try {
      Thread.currentThread().setContextClassLoader(urlCl);
      Context ctx = new InitialContext();
      System.out.println(ctx.lookup("tutorial/report.txt"));
      ctx.close();
    } catch (NamingException e) {
      e.printStackTrace();
    } finally {
      // Restore old loader
      Thread.currentThread().setContextClassLoader(prevCl);
    }
  } // main()
}

Yes, you can use URLClassLoader.. see example here. Doesn't use reflection.

-- edit --

Copying example from the link as suggested.

import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Hashtable;
import javax.naming.*;

public class ChangeLoader {
  public static void main(String[] args) throws MalformedURLException {
    if (args.length != 1) {
      System.err.println("usage: java ChangeLoader extra_classpath_url");
      System.exit(-1);
    }

    String url = args[0];
    // Save class loader so that we can restore later
    ClassLoader prevCl = Thread.currentThread().getContextClassLoader();

    // Use prevCl as parent, so we extend instead of replace
    ClassLoader urlCl = 
          URLClassLoader.newInstance(new URL[] {new URL(url)}, prevCl);

    try {
      Thread.currentThread().setContextClassLoader(urlCl);
      Context ctx = new InitialContext();
      System.out.println(ctx.lookup("tutorial/report.txt"));
      ctx.close();
    } catch (NamingException e) {
      e.printStackTrace();
    } finally {
      // Restore old loader
      Thread.currentThread().setContextClassLoader(prevCl);
    }
  } // main()
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文