简体   繁体   English

Java,运行时类重装

[英]Java, runtime class reloading

I am looking for a way to reload a class into Java at runtime. 我正在寻找一种在运行时将类重新加载到Java中的方法。 The motivation is to make debugging more efficient. 目的是使调试更加有效。 The application is a typical client/server design that synchronously processes requests. 该应用程序是典型的客户端/服务器设计,可以同步处理请求。 A "handler" object is instantiated for each request. 为每个请求实例化一个“处理程序”对象。 This is the only class I intend to dynamically replace. 这是我打算动态替换的唯一类。 Since each request deals with a fresh instance, reloading this class won't have any side-effects. 由于每个请求都处理一个新实例,因此重新加载此类不会有任何副作用。 In short, I do not want to restart the entire application every time there is a change to this module. 简而言之,我不想每次对该模块进行更改时都重新启动整个应用程序。

In my design, the Java process becomes aware that a .class file has been updated in the classpath in between requests. 在我的设计中,Java进程意识到请求之间的类路径中的.class文件已更新。 When this happens, the "handler" class is unloaded and a new one is loaded. 发生这种情况时,将卸载“ handler”类并加载一个新的类。

I know I can use the classLoader interface to load in a new class. 我知道我可以使用classLoader接口加载新类。 I seem to be having trouble finding the proper way of "unloading". 我似乎在寻找正确的“卸载”方法时遇到了麻烦。

Classes will be unloaded and garbage collected like any other object, if there is no remaining reference to them. 如果没有剩余的引用,将像其他任何对象一样卸载类并进行垃圾回收。 That means there must be no reachable instance of the class (as loaded by that particular classloader instance) and the classloader instance itself must be eligible for garbage collection as well. 这意味着必须没有该类的可访问实例(由该特定的classloader实例加载),并且该classloader实例本身也必须符合垃圾回收的条件。

So basically, all you have to do is to create a new classloader instance to load the new version of the class, and make sure that no references to instances of the old version remain. 因此,基本上,您要做的就是创建一个新的类加载器实例以加载该类的新版本,并确保不保留对旧版本实例的引用。

I believe that you actually need to have a hierarchy of classloaders, and in order to reload you actually get rid of the low level classloader (by normall GC means), and hence all the classes it loaded. 我相信您实际上需要具有一个类加载器的层次结构,并且要重新加载,实际上要摆脱低级类加载器(通过常规的GC手段),从而摆脱它加载的所有类。 So far as I know this technique is used by Java EE app servers for reloading applications, and there's all manner of fun results when framework code loaded in one classloader wants to use classes loaded somewhere else. 据我所知,Java EE应用程序服务器使用此技术来重新加载应用程序,当在一个类加载器中加载的框架代码想要使用在其他地方加载的类时,就会有各种有趣的结果。

As of 2015 also java's class reloading is a missing feature. 从2015年开始,java的类重载也是一个缺少的功能。

  • Use OSGi to create a class reloading application. 使用OSGi创建类重载应用程序。
  • Use jrebel for testing. 使用jrebel进行测试。 There are a few others which does the same thing. 还有其他一些人做同样的事情。
  • Use application server and externalize the parts which you want to reload into a separate web application. 使用应用程序服务器并将要重新加载的部分外部化到单独的Web应用程序中。 Then keep deploying/undeploying. 然后继续部署/取消部署。 You will eventually get some perm gen space overflow kind of errors due to dangling old ClassLoader instances. 由于旧的ClassLoader实例悬而未决,您最终将获得一些perm gen空间溢出错误。
  • Use a script runner to execute parts of changeable code. 使用脚本运行器执行可变代码的一部分。 JSR-223 Java Scripting API support for the scripting language "Java". JSR-223 Java脚本API支持脚本语言“ Java”。

I had written a series about class reloading. 我写了一系列有关类重载的文章。 But all of those methods are not good for production. 但是所有这些方法都不适合生产。

IMHO this class reloading is messy in java and its not worth trying it. 恕我直言,此类的重装在Java中很杂乱,不值得尝试。 But I would very much like this to be a specification in java. 但是我非常希望这是java中的规范。

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

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