Java 是什么让热部署成为一个;难题;?
在工作中,我们遇到了一个关于“”异常的问题,团队负责人认为这是JVM中的一个bug,与代码的热部署有关。在没有解释很多细节的情况下,他指出,热部署是一个“难题”,如此之难,以至于连.NET都还没有做到Java 是什么让热部署成为一个;难题;?,java,jvm,hotdeploy,Java,Jvm,Hotdeploy,在工作中,我们遇到了一个关于“”异常的问题,团队负责人认为这是JVM中的一个bug,与代码的热部署有关。在没有解释很多细节的情况下,他指出,热部署是一个“难题”,如此之难,以至于连.NET都还没有做到 我发现很多文章从鸟瞰的角度解释热部署,但总是缺少技术细节。有谁能给我一个技术解释,并解释为什么热部署是“一个难题”当加载一个类时,有关该类的各种静态数据都存储在PermGen中。只要存在对此类实例的活动引用,就不能对该类实例进行垃圾收集 我相信部分问题与GC是否应该从perm gen中删除旧类实例
我发现很多文章从鸟瞰的角度解释热部署,但总是缺少技术细节。有谁能给我一个技术解释,并解释为什么热部署是“一个难题”当加载一个类时,有关该类的各种静态数据都存储在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
认为运行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:大多数链接都与内存相关,而不是与类加载器体系结构相关,这对于理解热部署为何是一个问题非常有用。内存问题是解决方法的结果。关于运行线程的一个注意事项是:当我离开一个线程去睡觉的时候-