【问题标题】:Dynamically load a JAR using URLClassLoader?使用 URLClassLoader 动态加载 JAR?
【发布时间】:2011-06-07 02:48:09
【问题描述】:

我有一个程序需要能够在运行时动态加载 JAR - 环顾四周后,我相信它使用 URLClassLoader,但我不确定如何让它工作。 JAR“openup.jar”与程序位于同一目录中。

理想情况下我希望能够加载这个 JAR,而不必在其中指定每个单独的类。

【问题讨论】:

  • “加载这个 JAR 而不必知道里面有什么”到底是什么意思?那么,您究竟想从中加载什么?
  • 为什么要在不知道里面有什么的情况下加载一个罐子?您想将其作为 zip 文件处理还是对加载 java 类感兴趣?
  • 抱歉,措辞不佳-我的意思是,是否可以加载 JAR 而无需指定要使用的各个类。我正在使用的每个 JAR 中有 100 多个类(我需要使用所有这些类)——我的意思是是否可以在不为每个 JAR 中的每个类使用 getClass() 的情况下加载它们?跨度>
  • 您在哪里 使用这些类?在 Java 中,类不会通过未知的魔法“加载”。它们被加载是因为它们在某处被引用。什么确切地 引用了您希望从该 jar 中加载的类? “干净”的解决方案是创建一个能够加载相关 jar 的类加载器,并让 依赖于该 jar 的类从已将 jar 类加载器设置为其父级的类加载器加载。

标签: java dynamic jar


【解决方案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");
    }
}

How should I load Jars dynamically at runtime? 中确实提出了几乎相同的解决方案

【讨论】:

  • 这看起来是个糟糕的主意,因为它做了很多无法保证的假设:1.) ThisClass 的类加载器是 URLClassLoader; 2.) URLClassLoader 类有一个 addURL 方法(可以做你想做的事)和 3.) 你可以调用 setAccessible() (即没有安全管理器正在运行并禁止它)。
  • 是的,确实如此,但在我的情况下效果很好。你有更清洁的解决方案吗?
  • 谢谢 Morja,我认为,如果我正确理解了代码,这可能会达到我想要的效果,但如果不是,那么它仍然是一个答案,所以谢谢。
【解决方案2】:

这里我解释创建jar然后在另一个项目中动态加载jar的完整过程:

创建jar的步骤:

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

package newJar.com.example;

公共类 MyClass {

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

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

}

动态加载jar的步骤:

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

    公共类 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 Auto-generated catch block
         e.printStackTrace();
     }
    

    }

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

     File myJar = new File("Path of your jar ");//"D:\\ECLIPSE\\myjar.jar"
     CustomClass cls = new CustomClass();
     cls.getCall(myJar);
    

    }

}

这就是它如何使用 jar,如果 jar 在服务器上,则可以提供服务器路径而不是本地路径。

【讨论】:

    猜你喜欢
    • 2019-02-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-10
    • 2010-10-22
    相关资源
    最近更新 更多