Java 是什么让热部署成为一个;难题;?

Java 是什么让热部署成为一个;难题;?,java,jvm,hotdeploy,Java,Jvm,Hotdeploy,在工作中,我们遇到了一个关于“”异常的问题,团队负责人认为这是JVM中的一个bug,与代码的热部署有关。在没有解释很多细节的情况下,他指出,热部署是一个“难题”,如此之难,以至于连.NET都还没有做到 我发现很多文章从鸟瞰的角度解释热部署,但总是缺少技术细节。有谁能给我一个技术解释,并解释为什么热部署是“一个难题”当加载一个类时,有关该类的各种静态数据都存储在PermGen中。只要存在对此类实例的活动引用,就不能对该类实例进行垃圾收集 我相信部分问题与GC是否应该从perm gen中删除旧类实例

在工作中,我们遇到了一个关于“”异常的问题,团队负责人认为这是JVM中的一个bug,与代码的热部署有关。在没有解释很多细节的情况下,他指出,热部署是一个“难题”,如此之难,以至于连.NET都还没有做到


我发现很多文章从鸟瞰的角度解释热部署,但总是缺少技术细节。有谁能给我一个技术解释,并解释为什么热部署是“一个难题”

当加载一个类时,有关该类的各种静态数据都存储在PermGen中。只要存在对此类实例的活动引用,就不能对该类实例进行垃圾收集

我相信部分问题与GC是否应该从perm gen中删除旧类实例有关。通常,每次热部署时,新的类实例都会添加到PermGen内存池中,而现在未使用的旧类实例通常不会被删除。默认情况下,Sun JVM不会在PermGen中运行垃圾收集,但这可以通过可选的“java”命令参数启用

因此,如果热部署次数足够多,最终将耗尽PermGen空间

如果您的web应用在取消部署时未完全关闭(例如,如果它使线程保持运行),则该web应用使用的所有类实例都将固定在PermGen空间中。您重新部署,现在将所有这些类实例的另一个完整副本加载到PermGen中。您取消部署,线程继续运行,将另一组类实例固定在PermGen中。您重新部署并加载一整套副本。。。最终你的永久基因会被填满

有时,您可以通过以下方式解决此问题:

  • 向最近的Sun JVM提供命令参数,以在PermGen和类中启用GC。也就是说:
    -XX:+useConMarkSweepGC-XX:+CMSClassUnloadingEnabled-XX:+cmSClassWeapingEnabled
  • 使用不同的JVM,该JVM不使用固定大小的PermGen或对加载的类执行GC
但是,只有当您的web应用完全、干净地关闭时,这才有助于,不会留下对该web应用的类加载器加载的任何类的任何类实例的实时引用

由于类加载器泄漏,即使这样也不一定能解决问题。(在某些情况下,还有过多的插入字符串。)

查看以下链接了解更多信息(两个粗体的链接有很好的图表来说明部分问题)


一般来说,问题在于Java的安全模型实际上试图防止已加载的类再次加载

当然,Java从一开始就支持动态类加载,困难的是类重新加载

认为运行java应用程序注入恶意代码的新类是有害的(而且是有充分理由的)。例如,一个java.lang.String破解的实现来自internet,它在调用方法length()时删除一些随机文件,而不是创建字符串

所以,Java的构思方式(我认为.NETCLR的结果是,因为它在JVM中受到了高度的“启发”)是防止已经加载的类再次加载同一个VM

他们提供了一种覆盖这一“特征”的机制。类加载器,但类加载器的规则是,在尝试加载新类之前,它们应该向“父”类加载器请求权限,如果父类已经加载了该类,则忽略该新类

例如,我使用了从LDAP或RDBMS加载类的类加载器

当应用服务器成为JavaEE的主流时,热部署就成为Java世界的必要条件(同时也需要像spring这样的微容器来避免这种负担)

每次编译后重新启动整个应用服务器都会让人抓狂

所以应用服务器提供商,提供这个“自定义”类加载器来帮助热部署,并且使用配置文件,当在生产中设置时,应该禁用该行为。但折衷是,在开发过程中必须使用大量内存。因此,最好的方法是每3-4次部署重新启动一次

对于从一开始就设计用来加载类的其他语言,这种情况是不会发生的

例如,在Ruby中,您甚至可以向正在运行的类添加方法,在运行时重写方法,甚至向唯一的特定对象添加单个方法

当然,在这类环境中的折衷是内存和速度

我希望这有帮助

编辑

我在不久前发现了这个产品,它承诺重新加载尽可能简单。我不记得第一次写这个答案时的链接,我记得


sunjvm已经修复了PermGen空间,最终所有的空间都被消耗掉了(是的,显然是由于类加载器相关代码中的一个bug)=>OOM


如果您可以使用其他供应商的JVM(例如Weblogic one),它会动态扩展PermGen空间,因此您永远不会获得与PermGen相关的OOM。

您使用的是哪个版本的java?在早期的Sun 1.4.2中有一些bug,但它已经运行了很长时间。

顺便问一下,你将如何向你的团队领导透露这个消息?您是团队负责人吗?

Eddie——这不是保留类的原因,因为已经存在使用“旧”类定义的对象了吗?@Edie:大多数链接都与内存相关,而不是与类加载器体系结构相关,这对于理解热部署为何是一个问题非常有用。内存问题是解决方法的结果。关于运行线程的一个注意事项是:当我离开一个线程去睡觉的时候-