【问题标题】:Java reading files from dynamic external jarJava 从动态外部 jar 中读取文件
【发布时间】:2013-05-07 10:15:56
【问题描述】:

我正在尝试做并且一直在研究如何做很多天是有一个母罐子,它可以通过一个文件夹查看并动态加载所有罐子(不需要知道它们)为此为了工作,我需要一个名为plugin 的插件内的文件。我目前有一个可以启动插件的工作类加载器,但我无法读取plugin 文件。

这是我当前的代码:

加载.class

Load(JMenuBar Bar) {

ClassLoader currentThreadClassLoader = Thread.currentThread().getContextClassLoader();
        ClazzL = new URLClassLoader(new URL[]{new File("/home/grant/plugins/MenuPlugin.jar").toURL()}, currentThreadClassLoader);
        Thread.currentThread().setContextClassLoader(ClazzL);

        in = new BufferedReader(new InputStreamReader(ClazzL.getClass().getClassLoader().getResourceAsStream("/menuplugin/plugin")));

        System.out.println("in: " + in.readLine());


        Class c = ClazzL.loadClass("menuplugin.Main");//this works and loads properly
                                                      //it is just that it needs to
                                                      //load from `plugin` using
                                                      //in.readLine();
        API obj = (API) c.newInstance();
        obj.run(Bar);

}

错误是(第 44 行:in = new Buffered....)

Exception in thread "main" java.lang.NullPointerException
at menuaddon.Load.<init>(Load.java:42)
at menuaddon.Menuaddon.main(Menuaddon.java:39)
Java Result: 1

非常感谢您的帮助

完成的工作代码是:

ClassLoader currentThreadClassLoader = Thread.currentThread().getContextClassLoader();
        ClazzL = new URLClassLoader(new URL[]{new File("/home/grant/plugins/MenuPlugin.jar").toURL()}, currentThreadClassLoader);
        Thread.currentThread().setContextClassLoader(ClazzL);
        in = new BufferedReader(new InputStreamReader(ClazzL.getResourceAsStream("plugin")));
        classpath = in.readLine();
        Class c = ClazzL.loadClass(classpath);
        API obj = (API) c.newInstance();
        obj.run(Bar);

【问题讨论】:

  • 那么会发生什么?你收到in 了吗?
  • @Thilo in 返回Exception in thread "main" java.lang.NullPointerException at menuaddon.Load.&lt;init&gt;(Load.java:42) at menuaddon.Menuaddon.main(Menuaddon.java:39) Java Result: 1

标签: java dynamic external urlclassloader


【解决方案1】:

如果ClazzL实际上是一个变量,并且引用了类加载器,那么试试吧

ClazzL.getResourceAsStream("/menuplugin/plugin")

相反。如果您执行ClazzL.getClass().getClassLoader(),则您正在尝试从您的ClazzL 类的类加载器加载资源,而不是您创建的类加载器。

【讨论】:

  • ClazzL.getResourceAsStream("/menuplugin/plugin") = null
  • 试试不带前导/。 ClazzL.getResourceAsStream("menuplugin/plugin")
  • 奇怪。我已经创建了一个和你一样的例子,它工作得很好......你确定文件在你正在使用的名称和路径的 jar 中吗?
  • 我错的是plugin 位于/ 所以我应该拥有的是ClazzL.getResourceAsStream("plugin")
  • 感谢您现在的帮助,因为肯定会再次出现问题:)
【解决方案2】:
ClazzL.getClass().getClassLoader().getResourceAsStream("/menuplugin/plugin")

这不是从类加载器ClazzL 加载,而是从定义了 URLClassLoader 的类加载器(即系统类加载器)加载。

试试

ClazzL.getResourceAsStream("/menuplugin/plugin")

【讨论】:

  • ClazzL.getResourceAsStream("/menuplugin/plugin") = null
【解决方案3】:

使用getResource() 获取插件文件的 URL,然后在其上打开输入流。

编辑:您必须使用您使用创建的 URL 类加载器加载的类来执行此操作 - 而不是原始示例中的类加载器的类加载器 - 只看到父类加载器的类路径,而不是您刚刚创建的那个。

这段代码应该可以工作:

Class c = ClazzL.loadClass("menuplugin.Main");
URL pluginFileUrl = c.getResource("/menuplugin/plugin"); // This returns an URL representing resource on the classpath with a given file name.
InputStream inputStream = pluginFileUrl.openStream();

编辑 2:NilsH 的回答当然是更优雅的捷径。

【讨论】:

  • 应该可以。主要区别在于您现在使用的是正确的类加载器(与 jar 关联的类加载器),而不是系统类加载器。
  • 是的。我应该更好地解释自己。编辑了答案。
  • 关于这个编辑的事情是我在加载类之前需要文件......我正在从文件中获取插件的主类
  • c.getResourceAsStream("menuplugin/plugin") = null
  • 好的,那么 NilsH 上面的回答应该对你有用,不是吗?
猜你喜欢
  • 2012-10-28
  • 2014-06-05
  • 1970-01-01
  • 2015-11-30
  • 2015-12-23
  • 1970-01-01
  • 2011-04-09
  • 2012-12-25
  • 2013-12-08
相关资源
最近更新 更多