在由Class.forName(...)加载的jar上使用getResourceAsStream

时间:2013-06-28 16:03:16

标签: 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, loader);
// className is a String with the main class name in the jar

所有这一切都很好和花花公子 - 我可以在那个加载的类中调用方法,这一切都有效。

现在,我希望能够在该jar文件中存储各种资源,并让该类能够访问它们。我一直在看getResourceAsStream(),看起来应该是这样的:

InputStream in = this.getClass().getClassLoader().getResourceAsStream("path/to/my/test.txt");

...除了它总是返回null。我一直在盯着这个函数的例子和其他论坛帖子等等,但它们似乎都不符合我的具体情况:

  1. 使用URLClassLoader在运行时加载jar文件。
  2. jar文件不在classPath中。
  3. 我在这些情况下尝试做的事情实际上是可能的,还是我不得不求助于手动解压缩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());
        }
    }
    

    结果类中的函数:

    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();
        }
    }
    

    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
    

1 个答案:

答案 0 :(得分:1)

如发现的那样,问题是新的类加载器首先委托给父类加载器,后者正在查找类。

选项:

  • 确保当前的类加载器具有您要加载的类
  • 在构建新的null
  • 时指定父类加载器引用(可能是URLClassLoader?)