动态程序更新、运行时编译和类加载器
我有一个应用程序需要能够在不停止和重新启动的情况下更新自身的某些部分(一次一个类)。使用 JavaCompiler API,可以直接生成修改后的类源代码、重新编译、加载和实例化类。我可以在内存中完成这一切(没有从磁盘或网络读取文件)。
应用程序永远不会实例化此类的多个对象。对该对象只有两到三个引用。当修改后的类被加载并实例化时,所有这些引用都将更改为新对象。我还可以保证在加载修改后的类时,受影响的类中没有任何方法在另一个线程中运行。
我的问题是:我的类加载器在加载与之前加载的类同名的修改后的类时会出现问题吗?
如果我不在类加载器中显式实现加载类的缓存,是否可以避免问题?或者委托给父类加载器仍然会导致问题吗?
我希望使用类加载器的单个实例,但如果有必要,我可以在每次更新类时实例化一个新实例。
注意:我查看了 OSGI,它似乎比我需要的要多得多。
I have an application that needs the ability to update parts of itself (one class at a time) without stopping and restarting. With the JavaCompiler API, it is straightforward to generate modified class source code, recompile, load, and instantiate a class. I can do this all in memory (no files read from disk or net).
The application will never instantiate more than one object of such a class. There will only be two or three references to that object. When the modified class is loaded and instantiated, all those references will be changed to the new object. I can also probably guarantee that no method in the affected class is running in another thread while loading the modified class.
My question is this: will my class loader have problems loading a modified class with the same name as a class it previously loaded?
If I do not explicitly implement a cache of loaded classes in the class loader, would that avoid problems? Or could delegation to a parent class loader still cause a problem?
I hope to use a single instance of my class loader, but if necessary, I could instantiate a new one each time I update a class.
Note: I looked at OSGI and it seems to be quite a bit more than I need.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
http://tutorials.jenkov 上有一个有用的示例。 com/java-reflection/dynamic-class-loading-reloading.html
我们自己做了很多动态类重新加载(使用 Groovy 进行编译)。请注意,如果您有类依赖项,那么您可能需要在重新加载时重新编译这些依赖项。在开发堆栈中,我们跟踪这些依赖项,然后在依赖项过时时重新编译。在生产堆栈中,我们选择了非重新加载类加载器,并在发生任何变化时创建一个新的类加载器。所以你可以采用任何一种方法。
顺便说一句 - 您可能会在 http://grepcode.com/file/repo1.maven.org/maven2/org.codehaus.groovy/groovy-all/1.8.5/groovy/util/GroovyScriptEngine.java#GroovyScriptEngine 如果你想深入了解他们是如何做到的,这非常有趣。
There's a useful example on this at http://tutorials.jenkov.com/java-reflection/dynamic-class-loading-reloading.html
We do quite a bit of dynamic class reloading ourselves (using Groovy for compilations). Note if you've got class dependencies then you may need recompile these dependencies on reload. In dev stacks we keep a track of these dependencies and then recompile whenever dependencies become stale. In production stacks we opted for a non-reloading ClassLoader and create a new ClassLoader when ever anything changes. So you can do it either way.
BTW - you might find the GroovyScriptEngine at http://grepcode.com/file/repo1.maven.org/maven2/org.codehaus.groovy/groovy-all/1.8.5/groovy/util/GroovyScriptEngine.java#GroovyScriptEngine very interesting if you want to dig around how they do it.
好吧,它应该可以工作:当您加载新类时,它将替换相应表中的类名,并且内存应该被GC。也就是说,我会用一个真正的短程序对其进行严格的测试,该程序编译一个不平凡的类并替换它,比如说 10,000 次。
Okay, it should work: when you load the new class, it will replace the class name in the appropriate tables, and the memory should be GC'd. That said, I'd give it a strenuous test with a real short program that compiles a nontrivial class and replaces it, say 10,000 times.