有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java在使用不同的类加载器时看不到任何输出

所以我的问题是:

我有一些在DocuShare服务器上发生特定事件时调用的代码。我在自己的eventlistener中倾听事件。到目前为止,这一切都很顺利

这个监听器将调用其他单独开发并驻留在自己jar文件中的代码

目前,我们总是需要关闭整个系统,以部署其中一个JAR的新版本,这样才能使用它

因此,现在我试图创建一个系统,将该jarfile(不在类路径上)复制到另一个临时位置(因此没有jarlock),将jarfile加载到它自己的不同类加载器中并执行它。这样,当开发新版本时,我就可以简单地覆盖原始文件。然后,代码将查看JAR文件是否有修改,如果有,则执行相同的步骤

我在一个更简单的设置中成功地做到了这一点(调用了一个servlet),因此我知道“热部署”JAR的方法是有效的

然而,在本例中,在我开始使用单独的类加载器之前,代码运行良好。 我可以找到jarfile并检查差异,然后相应地加载jarfile,但当我尝试访问该类时,我在系统中没有得到任何输出。出或出系统。再也不会犯错了。jar中的代码没有正确执行,但我不明白为什么

额外信息:代码正在自己的线程中执行

概述正在发生的事情:

  1. DocuShare发送一个事件
  2. 我的听众听到了这个事件
  3. 监听器(实现java.util.concurrent.Executor)启动一个新线程(Runnable impl)
  4. Runnable impl创建一个新的类加载器,然后检查文件夹中是否有jar文件的新版本,如果有,它将把它复制到另一个目录,如果没有,它使用现有版本,将它加载到新类加载器的类路径上并执行它
  5. 从我用新的类加载器加载一个类的那一刻起,我在系统中没有看到任何打印的行。出/出系统。呃

代码示例(在Runnable.run()方法中):

URLClassLoader hotCL = new URLClassLoader(((URLClassLoader) systemCL).getURLs()); //new URLclassloader with URLs from system CL

//the following approach for putting the class on the classpath comes from another SO question from somebody else
Method m = cl.getClass().getDeclaredMethod("addURL", new Class[]{URL.class});
m.setAccessible(true);
m.invoke(cl, jar.toURI().toURL());
String cp = System.getProperty("java.class.path");
if (cp != null) {
    cp += File.pathSeparatorChar + jar.getCanonicalPath();
} else {
    cp = jar.toURI().getPath();
}

Logger.log(">>>>>>>> instantiating impl");  //this is printed in the System.out
Class<?> clsService = hotCL.loadClass(strService);  //strService is the class inside the separate jar
Object instance = clsService.newInstance();

Logger.log(">>>>>>>>>>>> class: " + clsService.getClass().toString()); //this is not printed in the System.out, neither is any log-statement after this or any error
//after this a method of the class instance is called but the code doesn't do anything.  Possibly an error but there's no error/stacktrace

类加载器有什么我不知道的吗?我只是不明白为什么我没有看到任何错误或代码被执行


共 (1) 个答案

  1. # 1 楼答案

    当类加载器试图加载从动态类引用的JDK类时,它可能挂起,因为它需要一个能够加载JDK类的父类加载器。您可以从当前上下文借用功能性父级,即:

    new URLClassLoader(urls, this.getClass().getClassLoader())
    

    如果在重新加载已实例化的类后遇到问题,请查看this thread