Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/394.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在运行时将文件添加到java类路径_Java_Runtime_Classpath - Fatal编程技术网

在运行时将文件添加到java类路径

在运行时将文件添加到java类路径,java,runtime,classpath,Java,Runtime,Classpath,是否可以在运行时将文件(不一定是jar文件)添加到java类路径。 具体来说,该文件已经存在于类路径中,我想要的是是否可以将该文件的修改副本添加到类路径中 谢谢,是的,你可以。如果要将其隔离,它需要位于其包结构中与编译代码的其余部分分开的目录中。然后将其基本目录放在命令行的类路径前面 是的,我相信这是可能的,但您可能必须实现自己的类加载器。我从来没有这样做过,但这是我可能会看到的道路 您可以使用更新的类所在的文件夹/jar的url尝试java.net.URLClassloader,并在创建新线程

是否可以在运行时将文件(不一定是jar文件)添加到java类路径。 具体来说,该文件已经存在于类路径中,我想要的是是否可以将该文件的修改副本添加到类路径中


谢谢,

是的,你可以。如果要将其隔离,它需要位于其包结构中与编译代码的其余部分分开的目录中。然后将其基本目录放在命令行的类路径前面

是的,我相信这是可能的,但您可能必须实现自己的类加载器。我从来没有这样做过,但这是我可能会看到的道路

您可以使用更新的类所在的文件夹/jar的url尝试java.net.URLClassloader,并在创建新线程时使用它而不是默认的类加载器

您只能将文件夹或jar文件添加到类加载器。因此,如果只有一个类文件,则需要首先将其放入适当的文件夹结构中

是一个相当丑陋的黑客,在运行时添加到SystemClassLoader:

import java.io.IOException;
import java.io.File;
import java.net.URLClassLoader;
import java.net.URL;
import java.lang.reflect.Method;

public class ClassPathHacker {

  private static final Class[] parameters = new Class[]{URL.class};

  public static void addFile(String s) throws IOException {
    File f = new File(s);
    addFile(f);
  }//end method

  public static void addFile(File f) throws IOException {
    addURL(f.toURL());
  }//end method


  public static void addURL(URL u) throws IOException {

    URLClassLoader sysloader = (URLClassLoader) ClassLoader.getSystemClassLoader();
    Class sysclass = URLClassLoader.class;

    try {
      Method method = sysclass.getDeclaredMethod("addURL", parameters);
      method.setAccessible(true);
      method.invoke(sysloader, new Object[]{u});
    } catch (Throwable t) {
      t.printStackTrace();
      throw new IOException("Error, could not add URL to system classloader");
    }//end try catch

   }//end method

}//end class

要访问受保护的方法
addURL
,必须进行反射。如果有SecurityManager,此操作可能会失败。

请尝试此操作以确定大小

private static void addSoftwareLibrary(File file) throws Exception {
    Method method = URLClassLoader.class.getDeclaredMethod("addURL", new Class[]{URL.class});
    method.setAccessible(true);
    method.invoke(ClassLoader.getSystemClassLoader(), new Object[]{file.toURI().toURL()});
}

这将编辑系统类加载器以包含给定的库jar。这很难看,但它可以工作。

我这样做的方法是使用我自己的类加载器

URLClassLoader urlClassLoader = (URLClassLoader) ClassLoader.getSystemClassLoader();
DynamicURLClassLoader dynalLoader = new DynamicURLClassLoader(urlClassLoader);
并创建以下类:

public class DynamicURLClassLoader extends URLClassLoader {

    public DynamicURLClassLoader(URLClassLoader classLoader) {
        super(classLoader.getURLs());
    }

    @Override
    public void addURL(URL url) {
        super.addURL(url);
    }
}
无需任何反射即可工作

我的解决方案:

File jarToAdd = new File("/path/to/file");

new URLClassLoader(((URLClassLoader) ClassLoader.getSystemClassLoader()).getURLs()) {
    @Override
    public void addURL(URL url) {
         super.addURL(url);
    }
}.addURL(jarToAdd.toURI().toURL());

谢谢大家的回复,我猜我们也可以在类路径中添加一个普通文件(不是类或jar等),但是我怎么知道会选择哪一个(最新添加的类路径或旧文件)啊,这是个问题。这在很大程度上取决于实现,因此您实际上不必在同一个类加载器中使用相同名称的类(或其他资源)。如果将它们放在单独的类加载器中,则会有一个规范。通常父类加载器采用优先顺序,对于Web应用程序,有时则相反(但仍然定义良好)。引导加载程序总是排在第一位。它真的依赖于实现吗?
URLClassLoader
的Javadoc将URL列表称为“搜索路径”,表示将“按照指定的顺序搜索”,而
addURL
的Javadoc则明确表示“附加”新条目。这听起来也定义得很好。这会抛出java.lang.ClassCastException:class jdk.internal.loader.ClassLoaders$AppClassLoader不能被强制转换为class java.net.UrlClassLoader有办法删除jar文件吗?或者用更新的版本替换它?这是一个副本吗?链接的问题是关于JAR的,不仅仅是文件,这个解决方案对我来说听起来不错,但它不起作用(可能是因为我使用的是Tomcat webapp?)。尝试从动态加载的JAR中包含的类调用方法时,我遇到了一个“找不到类”错误。即使在webapp中,其他解决方案也能工作。这不起作用,因为您创建了一个新的类加载器,其他类加载器仍然无法访问您添加到此类加载器的文件请解释您的代码的作用(在答案本身中,而不是在注释中)除了提供它之外。这不起作用,因为
URLClassLoader
中的
addURL
方法受
保护。但是你可以编写你自己的URLClassLoader来重写这个方法,修饰符应该是可以访问的。不过,我会编辑它一点,利用varargs使它更简单。工作!我通过删除数组减少了它,因为参数是varargs(到现在为止?),所以不再需要数组。