什么使热部署成为“难题”?

在工作中,我们遇到了“ PermGen内存不足 ”exception的问题,团队负责人认为这是JVM中的一个错误,这与代码的热部署有关。 他没有解释很多细节,他指出,热部署是一个“难题”,即使.NET也不这么做。

我发现很多文章都是从鸟瞰angular度解释热点部署,但总是缺乏技术细节。 任何人都可以给我一个技术解释,并解释为什么热部署是一个“难题”?

当一个类被加载时,关于这个类的各种静态数据被存储在PermGen中。 只要存在对此类实例的实时引用,就不能垃圾收集类实例。

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

因此,如果你部署足够多的时间,你最终会耗尽你的PermGen空间。

如果您的Web应用程序在未部署时未完全closures(例如,如果它留下了一个正在运行的线程),则该Web应用程序使用的所有Class实例将被固定在PermGen空间中。 您重新部署,现在已经将所有这些Class实例的另一个完整副本加载到PermGen中。 您将取消部署,并且线程继续进行,在PermGen中钉住另一组类实例。 你重新部署和加载一整套的副本…最终你的PermGen填满了。

有时你可以通过以下方式解决

  • 将命令参数提供给最近的Sun JVM以在PermGen和类中启用GC。 即: -XX:+UseConcMarkSweepGC -XX:+CMSClassUnloadingEnabled -XX:+CMSPermGenSweepingEnabled
  • 使用不使用固定大小的PermGen的不同JVM,或者在加载的类上执行GC

但是, 只有当您的web应用程序完全closures并且干净地closures时,才会有所帮助,而不会为该Web App的类加载器加载的任何类的实例引用。

即使这不会解决问题,由于类加载器泄漏。 (在某些情况下,还有太多的string)。

看看下面的链接更多(两个粗体的有很好的图来说明问题的一部分)。

  • 类加载器泄漏:可怕的“java.lang.OutOfMemoryError:PermGen空间”exception
  • 未知的一代:烫发
  • 呈现永久的一代
  • Tomcat Wiki:如何处理内存不足错误

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

当然,Java从一开始就支持dynamic类加载,难于重新加载类。

这被认为是有害的(并有一个很好的理由),一个正在运行的Java应用程序注入了一个带有恶意代码的新类。 例如,一个java.lang.String从互联网破解的实现,不是创buildstring,而是删除一些调用方法length()的随机文件hile。

所以,他们构思了Java(我认为.NET CLR是因为它在JVM中被高度“启发”),以防止已经加载的类再次加载相同的VM。

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

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

当Java应用服务器成为Java EE的主stream时(也为了避免这种负担而需要像Spring那样的微型容器),热门部署成为Java世界的必需品。

每次编译之后重新启动整个应用程序服务器会让任何人都疯狂。

所以,应用服务器提供商,提供这个“自定义”类加载器来帮助热部署,并使用configuration文件,该行为,应该在生产中被禁用。 但是权衡是你必须在开发中使用大量的内存。 所以这样做的好方法是每3 – 4次部署重新启动一次。

对于从一开始就devise的其他语言来说,这不会发生。

比如在Ruby中,你甚至可以将方法添加到正在运行的类中,在运行时重写一个方法,甚至可以将一个方法添加到唯一的特定对象中。

这种环境的权衡当然是记忆和速度。

我希望这有帮助。

编辑

我发现这个产品前一段时间,承诺重新加载是尽可能简单。 当我第一次写这个答案的时候,我不记得这个链接,而我也是。

它是ZeroTurnaround的JavaRebel

Sun的JVM已经修复了PermGen的空间,并且最终都被消耗了(是的,显然是由于类加载器相关的代码中的错误)=> OOM。

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

你正在使用哪个版本的java? Sun 1.4.2早期有一些bug,但是它已经工作很长时间了。
顺便说一句,你将如何打破这个消息,你的团队领导? 你是团队领导吗?

Interesting Posts