Java 在类.forName(…)加载的jar上使用getResourceAsStream

Java 在类.forName(…)加载的jar上使用getResourceAsStream,java,class,jar,Java,Class,Jar,现在,在我开始之前,我对Java还不熟悉,我有点陷入了困境 我有一个系统,可以将jar文件中的类以插件的形式加载到我的应用程序中: URLClassLoader loader = new URLClassLoader(urlList); // urlList is a 1 slice URL[] with a single URL to a jar file in it Class<?> toolClass = Class.forName(className, true, loade

现在,在我开始之前,我对Java还不熟悉,我有点陷入了困境

我有一个系统,可以将jar文件中的类以插件的形式加载到我的应用程序中:

URLClassLoader loader = new URLClassLoader(urlList);
// urlList is a 1 slice URL[] with a single URL to a jar file in it
Class<?> toolClass = Class.forName(className, true, loader);
// className is a String with the main class name in the jar
。。。除非它总是返回null。我一直在关注有关此功能的示例和其他论坛帖子等,但它们似乎都不符合我的具体情况:

  • jar文件在运行时使用URLClassLoader加载
  • jar文件不在类路径中
  • 那么,我在这些情况下试图做的事情实际上是可能的,还是我必须求助于手动解压jar文件以获取资源?(老实说,我不想那样做。)


    编辑:以下是我正在使用的函数:

    加载jar文件:

    public void loadPlugin(File jar)
    {
        try {
            URL[] urlList = new URL[1];
            urlList[0]  = jar.toURI().toURL();
    
            URLClassLoader loader = new URLClassLoader(urlList);
    
            String className = null;
            className = findClassInZipFile(jar); // This just walks the zip file looking for the class
    
            if (className == null) {
                return;
            }
    
            JarFile jf = new JarFile(jar);
            Manifest manifest = jf.getManifest();
            Attributes manifestContents = manifest.getMainAttributes();
    
            Map pluginInfo = new LinkedHashMap();
            pluginInfo.put("version", manifestContents.getValue("Version"));
            pluginInfo.put("compiled", manifestContents.getValue("Compiled"));
            pluginInfo.put("jarfile", jar.getAbsolutePath());
    
            Class<?> toolClass;
            try {
                toolClass = Class.forName(className, true, loader);
            } catch (Exception ex) {
                ex.printStackTrace();
                return;
            }
            Tool tool = (Tool) toolClass.newInstance();
    
            // If the setInfo method doesn't exist we don't care.
            try {
                tool.setInfo(pluginInfo);
            } catch (Exception blah) {
            }
            plugins.put(className, tool);
        } catch (Exception e) {
            System.err.println(e.getMessage());
        }
    }
    
    jar文件如下所示:

       0 Fri Jun 28 16:52:32 BST 2013 META-INF/
     140 Fri Jun 28 16:52:30 BST 2013 META-INF/MANIFEST.MF
       0 Fri Jun 28 16:52:32 BST 2013 uecide/
       0 Fri Jun 28 16:52:32 BST 2013 uecide/app/
       0 Fri Jun 28 16:52:32 BST 2013 uecide/app/tools/
    1880 Fri Jun 28 16:52:32 BST 2013 uecide/app/tools/ExportToMPLABX.class
    2754 Fri Jun 28 16:52:32 BST 2013 uecide/app/tools/test.txt
    

    正如所发现的,问题是新类加载器首先委托给父类加载器,父类加载器正在查找类

    选项:

    • 确保当前类加载器没有您试图加载的类
    • 在构造新的
      URLClassLoader
      时,指定父类加载器引用(可能是
      null
      ?)

    这应该是绝对好的。我怀疑您提供了错误的资源名称。例如,资源名称区分大小写-您是否仔细检查了提供的确切名称?资源路径必须以
    /
    开头!您的示例中没有
    /
    ,这可能是您的问题所在here@fge:这是不正确的。如果使用
    Class.getResourceAsStream()
    从根开始,而不是从类的包开始,则它们必须以
    /
    开始。如果使用
    ClassLoader.getResourceAsStream()
    ,则它们不能以
    /
    开头。在示例代码中,这个
    是什么?它与创建URLClassLoader的对象是同一个对象,还是从jar加载的类的实例?@Majenko:您是否仔细检查了
    this.getClass().getClassLoader()
    是否返回了您期望的类加载器?有可能它正在委托给类中的另一个类。forName…对URLClassLoader的父类加载器使用null会导致它无法找到类。@Majenko:这很有趣-这表明它在查找jar文件时出现了问题。嗯,我想这是值得调试的。我想我会坚持在加载时将加载程序传递给类。我想我没有多余的大脑来思考这个问题。
    public void run() {
        try {
            InputStream in = this.getClass().getClassLoader().getResourceAsStream("uecide/app/tools/test.txt");
            if (in == null) {
                System.err.println("FAIL!!!");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
       0 Fri Jun 28 16:52:32 BST 2013 META-INF/
     140 Fri Jun 28 16:52:30 BST 2013 META-INF/MANIFEST.MF
       0 Fri Jun 28 16:52:32 BST 2013 uecide/
       0 Fri Jun 28 16:52:32 BST 2013 uecide/app/
       0 Fri Jun 28 16:52:32 BST 2013 uecide/app/tools/
    1880 Fri Jun 28 16:52:32 BST 2013 uecide/app/tools/ExportToMPLABX.class
    2754 Fri Jun 28 16:52:32 BST 2013 uecide/app/tools/test.txt