使用 URLClassLoader 重新加载 jar 的问题 [英] Problem reloading a jar using URLClassLoader

查看:38
本文介绍了使用 URLClassLoader 重新加载 jar 的问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要为现有应用程序的某些部分添加插件功能.我希望能够在运行时添加一个 jar,并且应用程序应该能够在不重新启动应用程序的情况下从 jar 加载一个类.到现在为止还挺好.我在网上找到了一些使用 URLClassLoader 的示例,效果很好.

我还希望能够在 jar 的更新版本可用时重新加载相同的类.我再次找到了一些示例,据我所知,实现这一目标的关键是我需要为每个新加载使用一个新的类加载器实例.

我编写了一些示例代码,但遇到了 NullPointerException.首先让我向你们展示代码:

package test.misc;导入 java.io.File;导入 java.net.URL;导入 java.net.URLClassLoader;导入 plugin.misc.IPlugin;公共类 TestJarLoading {公共静态无效主(字符串 [] args){IPlugin 插件 = null;而(真){尝试 {File file = new File("C:\plugins\test.jar");String classToLoad = "jartest.TestPlugin";URL jarUrl = new URL("jar", "","file:" + file.getAbsolutePath()+"!/");URLClassLoader cl = new URLClassLoader(new URL[] {jarUrl}, TestJarLoading.class.getClassLoader());类加载类 = cl.loadClass(classToLoad);plugin = (IPlugin)loadedClass.newInstance();plugin.doProc();} 捕获(异常 e){e.printStackTrace();} 最后 {尝试 {线程睡眠(30000);} catch (InterruptedException e) {e.printStackTrace();}}}}}

IPlugin 是一个简单的接口,只有一个 doProc 方法:

公共接口IPlugin {void doProc();}

和 jartest.TestPlugin 是这个接口的一个实现,其中 doProc 只是打印出一些语句.

现在,我将 jartest.TestPlugin 类打包到一个名为 test.jar 的 jar 中,并将其放在 C:plugins 下并运行此代码.第一次迭代运行顺利,类加载没有问题.

当程序执行 sleep 语句时,我将 C:plugins est.jar 替换为包含相同类的更新版本的新 jar,并等待下一次迭代 while.现在这是我不明白的地方.有时更新的类会重新加载而不会出现问题,即下一次迭代运行良好.但有时,我会看到抛出异常:

java.lang.NullPointerException在 java.io.FilterInputStream.close(FilterInputStream.java:155)在 sun.net.www.protocol.jar.JarURLConnection$JarURLInputStream.close(JarURLConnection.java:90)在 sun.misc.Resource.getBytes(Resource.java:137)在 java.net.URLClassLoader.defineClass(URLClassLoader.java:256)在 java.net.URLClassLoader.access$000(URLClassLoader.java:56)在 java.net.URLClassLoader$1.run(URLClassLoader.java:195)在 java.security.AccessController.doPrivileged(Native Method)在 java.net.URLClassLoader.findClass(URLClassLoader.java:188)在 java.lang.ClassLoader.loadClass(ClassLoader.java:307)在 java.lang.ClassLoader.loadClass(ClassLoader.java:252)在 test.misc.TestJarLoading.main(TestJarLoading.java:22)

我在网上搜索并摸不着头脑,但无法真正得出关于为什么会抛出此异常以及为什么会抛出任何结论的结论 - 只是有时,并非总是如此.

我需要您的经验和专业知识才能理解这一点.这段代码有什么问题?请帮忙!!

如果您需要更多信息,请告诉我.感谢观看!

解决方案

此行为与 错误
此处 记录了 2 个解决方法>

I need to add plugin functionality to an existing application for certain parts of the application. I want to be able to add a jar at runtime and the application should be able to load a class from the jar without restarting the app. So far so good. I found some samples online using URLClassLoader and it works fine.

I also wanted the ability to reload the same class when an updated version of the jar is available. I again found some samples and the key to achieving this as I understand is that I need to use a new classloader instance for each new load.

I wrote some sample code but hit a NullPointerException. First let me show you guys the code:

package test.misc;

import java.io.File;
import java.net.URL;
import java.net.URLClassLoader;

import plugin.misc.IPlugin;

public class TestJarLoading {

    public static void main(String[] args) {

        IPlugin plugin = null;

        while(true) {
            try {
                File file = new File("C:\plugins\test.jar");
                String classToLoad = "jartest.TestPlugin";
                URL jarUrl = new URL("jar", "","file:" + file.getAbsolutePath()+"!/");
                URLClassLoader cl = new URLClassLoader(new URL[] {jarUrl}, TestJarLoading.class.getClassLoader());
                Class loadedClass = cl.loadClass(classToLoad);
                plugin = (IPlugin) loadedClass.newInstance();
                plugin.doProc();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                try {
                    Thread.sleep(30000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

IPlugin is a simple interface with just one method doProc:

public interface IPlugin {
    void doProc();
}

and jartest.TestPlugin is an implementation of this interface where doProc just prints out some statements.

Now, I package the jartest.TestPlugin class into a jar called test.jar and place it under C:plugins and run this code. The first iteration runs smoothly and the class loads without issues.

When the program is executing the sleep statement, I replace C:plugins est.jar with a new jar containing an updated version of the same class and wait for the next iteration of while. Now here's what I don't understand. Sometimes the updated class gets reloaded without issues i.e. the next iteration runs fine. But sometimes, I see an exception thrown:

java.lang.NullPointerException
at java.io.FilterInputStream.close(FilterInputStream.java:155)
at sun.net.www.protocol.jar.JarURLConnection$JarURLInputStream.close(JarURLConnection.java:90)
at sun.misc.Resource.getBytes(Resource.java:137)
at java.net.URLClassLoader.defineClass(URLClassLoader.java:256)
at java.net.URLClassLoader.access$000(URLClassLoader.java:56)
at java.net.URLClassLoader$1.run(URLClassLoader.java:195)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:188)
at java.lang.ClassLoader.loadClass(ClassLoader.java:307)
at java.lang.ClassLoader.loadClass(ClassLoader.java:252)
at test.misc.TestJarLoading.main(TestJarLoading.java:22)

I have searched on the net and scratched my head but can't really arrive at any conclusion as to why this exception is thrown and that too - only sometimes, not always.

I need your experience and expertise to understand this. What's wrong with this code? Please help!!

Let me know if you need any more info. Thanks for looking!

解决方案

This behaviour is related to a bug in the jvm
2 workarounds are documented here

这篇关于使用 URLClassLoader 重新加载 jar 的问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆