2010-07-28 36 views
2

从概念上说,当我加载新的Jar时,我正在做什么? URLClassloader是唯一的选择吗?我应该如何形成这些URL来指向包含更多jar的子目录。动态Jar加载令我困惑

如果有人感觉超级大方,一些演示代码做会以下是很有益的(假设“罐子/ a.jar文件”包含“MyClass的”,我们要实例):

  1. 从一个子目录加载一些罐子
  2. 返回从中
  3. 实例化类

回答

4

概念特定类,我是什么DOI当我加载一个新的罐子时?

从概念上讲,您并未加载新的JAR。相反,您正在定义一个类加载器,它将根据需要从JAR文件加载代码和其他资源。

是URLClassloader唯一的选择吗?

从理论上讲,您可以实现自己的子类ClassLoader,但这对于您正在尝试执行的操作不是必需的。

我该如何形成这些URL来指向包含更多jar的子目录。

这是我认为你的问题的核心。该URLClassLoader构造解释URL[]参数如下:

“与一个‘/’结尾被假定为是指一个目录下的任何URL否则,URL被假定为是指一个JAR文件,这将是根据需要下载并打开。“

在上述引用文本的第一种情况下,目录被假定为包含要加载的资源的树的根目录。

但我收集你正试图建立一个类加载器,将加载从给定目录中的所有JAR文件。为此,您需要:

  1. 阅读目录并为任何JAR文件构建File对象的列表。
  2. 创建一个数组来保存相同数量的URL实例。
  3. 对于每个JAR文件File,请使用File.toURL()创建URL并添加到该数组。 (使用File.toURL()意味着您将获得将在您的平台上运行的JAR文件的kosher“file:”URL)。
  4. 使用URL阵列创建URLClassLoader
0

如果已知jar包的列表,那么一个潜在的更好/更简单的解决方案就是将一个Class-Path条目添加到父jar的清单中。这样你就可以完全避免使用自定义类加载器。

Class-Path: jars/A.jar 

显然这不会在构建时不知道相关的罐子的地方。

+0

究竟怎样的是 '动态的' 负荷? – djangofan 2010-11-03 22:38:40

2

真的很短的版本:当你加载一个新的JAR时,你给了Java寻找类的新地方。

对于一个较长的解释,维基百科有与此相关的文章:http://en.wikipedia.org/wiki/Java_Classloader

另外,可以尝试:http://onjava.com/pub/a/onjava/2005/01/26/classloading.html

URLClassLoader的是不是你唯一的选择;退房http://download-llnw.oracle.com/javase/tutorial/deployment/jar/apiindex.html

回复:网址应如何形成的,从Java文档(http://download-llnw.oracle.com/javase/7/docs/api/java/net/URLClassLoader.html):

这个类加载器用于从URL中既指JAR文件的搜索路径加载类和资源,目录。任何以'/'结尾的URL都被假定为指向一个目录。否则,假定该URL是指将根据需要打开的JAR文件。

How should I load Jars dynamically at runtime?改编:

URLClassLoader child = new URLClassLoader (new URL("jars/A.jar"), this.getClass().getClassLoader()); 
Class classToLoad = Class.forName ("com.myClass", true, child); 
Method method = classToLoad.getDeclaredMethod ("myMethod"); 
Object instance = classToLoad.newInstance(); 
Object result = method.invoke (instance); 

而且,上面链接的答案列出来URLClassLoader的一些更多的选择(他们提到的OSGi,JCL,和其他几个人,其中没有我有任何经验或我会在这里说点什么)。

HTH

0

简单的方法是,以确保相关的JAR在类路径中启动程序之前。


如果要从子目录加载,则需要确定要提供给URLClassLoader的JAR路径。您可以使用这样的事情让你的程序的路径:

new File(MyClass.class.getProtectionDomain().getCodeSource().getLocation().toURI().getPath()) 

这是一个黑客攻击的一位,但我不知道任何官方的方式来获得一个Java程序的路径。


如果要动态加载一个JAR,这样你可以使用它,如果你已经在类路径中指定,看看这个thread。这绝对是不受支持的黑客领域,但它也很简单。

修改,我使用的版本:

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

/** 
* Hack to modify classpath at runtime. Can be used to load JARs as if they were 
* loaded from the start. 
* 
* Warning: May break if URLClassLoader changes 
* 
* @author Antony Miguel 
*/ 
public class ClasspathHacker { 
    /** 
    * Add a file to the classpath. 
    * 
    * @param pPath 
    *   path to the file 
    */ 
    public static void addFile(String pPath) { 
     File f = new File(pPath); 
     addFile(f); 
    } 

    /** 
    * Add a file to the classpath. 
    * 
    * @param pFile 
    *   the file to be added 
    */ 
    public static void addFile(File pFile) { 
     try { 
      addURL(pFile.toURI().toURL()); 
     } catch (MalformedURLException e) { 
      e.printStackTrace(); 
     } 
    } 

    /** 
    * Add the content pointed to by a URL to the classpath. 
    * 
    * @param pURL 
    *   the URL pointing to the content to be added 
    */ 
    public static void addURL(URL pURL) { 
     /* 
     * Use reflection to call addURL on the system classloader, which we 
     * expect to be a URLClassLoader 
     */ 
     Method method; 
     try { 
      method = URLClassLoader.class.getDeclaredMethod("addURL", 
        new Class[] { URL.class }); 
      method.setAccessible(true); 
      method.invoke(ClassLoader.getSystemClassLoader(), 
        new Object[] { pURL }); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
    } 
}