Java从动态外部jar读取文件

时间:2013-05-07 10:15:57

标签: java dynamic external urlclassloader

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

这是我目前的代码:

Load.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);

3 个答案:

答案 0 :(得分:4)

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

ClazzL.getResourceAsStream("/menuplugin/plugin")

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

答案 1 :(得分:2)

使用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的答案当然是一个更优雅的捷径。

答案 2 :(得分:2)

ClazzL.getClass().getClassLoader().getResourceAsStream("/menuplugin/plugin")

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

尝试

ClazzL.getResourceAsStream("/menuplugin/plugin")