使用URLClassLoader动态加载JAR文件?

3
我有一个程序需要在运行时动态加载JAR - 经过搜索,我认为这需要使用URLClassLoader,但我不确定如何让它工作。 JAR文件“openup.jar”与程序位于同一目录中。
理想情况下,我希望能够加载此JAR,而无需指定其中每个单独的类。

3
可能是如何在运行时动态加载Jars?的重复问题。 - dogbane
你所说的“不需要知道 JAR 文件内部内容即可加载它”,具体是什么意思?那么,你想要从中加载什么呢? - Joachim Sauer
为什么你想要在不知道 jar 文件内部内容的情况下加载它?你是想将其处理成 zip 文件,还是有兴趣加载 Java 类? - pgras
抱歉,我的措辞有误 - 我的意思是,在不必指定要使用的各个类的情况下,是否可以加载JAR。我正在使用的每个JAR中都有100多个类(我都需要使用),我的意思是,是否可能在每个JAR中不使用getClass()来加载它们? - Myn
你在哪里使用这些类?在Java中,类不是通过未知的魔法“加载”的。它们之所以被加载,是因为它们在某个地方被引用了。到底是什么引用了你想要从那个jar包中加载的类?“干净”的解决方案是创建一个类加载器,能够加载相关的jar包,并且让依赖于该jar包的类从一个已经将jar包类加载器设置为其父级的类加载器中加载。 - Joachim Sauer
很抱歉,我不确定你的意思,但我认为我的问题无法解决。我相信我必须经过繁琐的任务,逐个引用我需要使用的每个类。感谢大家的建议。 - Myn
2个回答

1

我成功使用的:

@SuppressWarnings("unchecked")
public void addURL(URL u) throws IOException {
    URLClassLoader sysLoader = (URLClassLoader) ThisClass.class.getClassLoader();
    URL urls[] = sysLoader.getURLs();
    for (int i = 0; i < urls.length; i++) {
        if (urls[i].toString().equalsIgnoreCase(u.toString())) {
            return;
        }
    }
    Class sysclass = URLClassLoader.class;
    try {
        Method method = sysclass.getDeclaredMethod("addURL", parameters);
        method.setAccessible(true);
        method.invoke(sysLoader, new Object[] { u });
    } catch (Throwable t) {
        throw new IOException("Error, could not add URL to system classloader");
    }
}

一个几乎相同的解决方案确实在如何在运行时动态加载Jars?中提出。


1
这看起来像是一个可怕的想法,因为它做了很多假设,而这些假设并不保证:1)ThisClass 的类加载器是 URLClassLoader;2)URLClassLoader 类有一个 addURL 方法(它所做的正是你想要的);3)你可以调用 setAccessible()(即没有运行安全管理器并禁止该操作)。 - Joachim Sauer
1
是的,那是真的,但在我的情况下它运行良好。你有更简洁的解决方案吗? - morja
谢谢Morja,我认为,如果我正确理解了代码,这可能会做到我想要的,但如果不是,那也是一个答案,所以谢谢你。 - Myn

0

在这里,我将解释创建jar文件的完整流程,并动态加载到另一个项目中:

创建jar的步骤:

  1. 在任何IDE(Eclipse)中创建新项目。
  2. 在包中添加示例类(在我的情况下是MyClass)。
  3. 右键单击该项目,然后导出为jar文件,并在系统位置上给出本地路径以保存jar文件(右键单击 -> 导出 -> 选择java/jar文件 -> 下一步 -> 给出路径 -> 完成)。
  4. 然后,在给定位置会有可用的jar文件。

包newJar.com.example;

public class MyClass {

public MyClass() {
    // TODO Auto-generated constructor stub
}

public void helloWorld() {
    System.out.println("Hello from the helloWorld");
}

}

动态加载jar的步骤:

  1. 创建一个新项目并添加以下代码:

    public class CustomClass {

    public CustomClass() { // TODO 自动生成的构造函数存根 }

    public void getCall(File myJar) {

     try {
    
         URLClassLoader loader = new URLClassLoader(new URL[] { myJar.toURI().toURL() },
                 CustomClass.class.getClass().getClassLoader());
    
         Class classToLoad = Class.forName("newJar.com.example.MyClass", true, loader);
         System.out.println(classToLoad);
         Method method = classToLoad.getDeclaredMethod("helloWorld");
         Object instance = classToLoad.newInstance();
         Object result = method.invoke(instance);
    
     } catch (MalformedURLException | ClassNotFoundException | NoSuchMethodException | SecurityException
             | InstantiationException | IllegalAccessException | IllegalArgumentException
             | InvocationTargetException e) {
         // TODO 自动生成的 catch 块
         e.printStackTrace();
     }
    

    }

    public static void main(String[] args) { // TODO 自动生成的方法存根

     File myJar = new File("你的jar包路径");//"D:\\ECLIPSE\\myjar.jar"
     CustomClass cls = new CustomClass();
     cls.getCall(myJar);
    

    }

}

这是如何利用jar文件的方法,如果jar文件在服务器上,则可以使用服务器路径而不是本地路径。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接