简体   繁体   English

Java从动态外部jar读取文件

[英]Java reading files from dynamic external jar

What i am trying to do and have been researching on how to do for many days is to have a mother jar that looks through a folder and loads all the jars in there dynamically ( Not really needing to know about them ) for this to work i need a file inside the plugins called plugin . 我正在尝试做并且一直在研究如何做很多天的事情是有一个可以通过文件夹查看并动态加载其中所有罐子的母罐(实际上并不需要了解它们),这样我才能正常工作在插件中需要一个名为plugin的文件。 I Currently have a working class loader that can start the plugins but i can not read the plugin file. 我目前有一个可以启动插件的工作类加载器,但我无法读取plugin文件。

here is my current code: 这是我当前的代码:

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

}

the error is (line 44: in = new Buffered....) 错误是(第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

much help appreciated 非常感谢帮助

the finished working code is: 完成的工作代码是:

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

If ClazzL actually is a variable, and references the classloader, then try just 如果ClazzL实际上是一个变量,并且引用了类加载器,则尝试

ClazzL.getResourceAsStream("/menuplugin/plugin")

instead. 代替。 If you do ClazzL.getClass().getClassLoader() , you're trying to load the resource from the classloader of your ClazzL class, not the classloader you have created. 如果执行ClazzL.getClass().getClassLoader() ,则尝试从ClazzL类的类加载器而不是已创建的类加载器加载资源。

Get an URL of the plugin file using getResource() , then open an input stream on it. 使用getResource()获取插件文件的URL,然后在其上打开输入流。

EDIT: You have to do it using a class that you've loaded using the URL classloader you created - not the classloader's classloader as in your original example - that only sees the classpath of parent classloader, not the one you've just created. 编辑:您必须使用您使用创建的URL类加载器加载的类而不是如原始示例中那样的类加载器的类加载器)加载类,该类只能看到父类加载器的类路径,而不是您刚刚创建的类路径。

This code should work: 此代码应工作:

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

EDIT 2: NilsH's answer is of course a much more elegant shortcut. 编辑2:NilsH的答案当然是一个更为优雅的捷径。

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

That is not loading from the classloader ClazzL , but from the class loader that defines URLClassLoader (ie the system classloader). 那不是从类加载器ClazzL加载,而是从定义URLClassLoader的类加载器(即系统类加载器)加载。

Try 尝试

ClazzL.getResourceAsStream("/menuplugin/plugin")

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM