我有一个应用程序,需要能够在不停止和重新启动的情况下更新自身的一部分(一次一个类)。使用JavaCompiler API,可以直接生成修改后的类源代码,重新编译,加载和实例化类。我可以在内存中完成所有操作(没有从磁盘或网络读取的文件)。
应用程序永远不会实例化这样一个类的多个对象。只有两到三个对象的引用。加载并实例化修改后的类时,所有这些引用都将更改为新对象。我也可以保证在加载修改后的类时,受影响的类中没有方法在另一个线程中运行。
我的问题是:我的类加载器是否会在加载修改后的类时遇到问题?修改后的类与之前加载的类名相同?
如果我没有在类加载器中显式实现加载类的缓存,那会避免出现问题吗?或者委托给父类加载器仍然会导致问题?
我希望使用我的类加载器的单个实例,但如果有必要,我可以在每次更新类时实例化一个新实例。
注意:我查看了OSGI,它看起来比我需要的要多得多。
答案 0 :(得分:1)
在http://tutorials.jenkov.com/java-reflection/dynamic-class-loading-reloading.html
上有一个有用的例子我们自己做了很多动态类重装(使用Groovy进行编译)。请注意,如果您有类依赖项,那么您可能需要在重新加载时重新编译这些依赖项。在dev堆栈中,我们跟踪这些依赖关系,然后在依赖关系变得陈旧时重新编译。在生产堆栈中,我们选择了非重载的ClassLoader,并在发生任何变化时创建一个新的ClassLoader。所以你可以这样做。
BTW - 你可能会发现http://grepcode.com/file/repo1.maven.org/maven2/org.codehaus.groovy/groovy-all/1.8.5/groovy/util/GroovyScriptEngine.java#GroovyScriptEngine的GroovyScriptEngine非常有趣,如果你想挖掘它们是如何做到的。
答案 1 :(得分:0)
好的,它应该工作:当你加载新类时,它将替换相应表中的类名,并且内存应该是GC'd。也就是说,我会用一个真正的简短程序给它做一个艰苦的测试,编写一个非常重要的程序并替换它,比如10,000次。