问题描述
在工作中,我们遇到了的问题例外情况,团队领导决定它是JVM中的一个错误 - 与代码的热部署有关。在没有解释许多细节的情况下,他指出热部署是一个难题,即使.NET还没有这么做也很难。
At work, we've been having a problem with "PermGen out of memory" exceptions, with the team lead deciding it was a bug in the JVM - something related to hot-deployment of code. Without explaining many details, he pointed out that hot deployment is a "hard problem", so hard that even .NET doesn't do it yet.
我发现了很多从鸟瞰图解释热部署的文章,但总是缺乏技术细节。有没有人能指出我的技术解释,并解释为什么热部署是一个难题?
I found a lot of articles explaining hot deployment from the bird's-eye-view, but always lacking technical details. Could anyone point me to a technical explanation, and explain why hot deployment is "a hard problem"?
推荐答案
当一个班级是加载后,有关该类的各种静态数据存储在PermGen中。只要存在对此Class实例的实时引用,就不能对类实例进行垃圾回收。
When a class is loaded, various static data about the class is stored in PermGen. As long as a live reference to this Class instance exists, the class instance cannot be garbage collected.
我认为问题的一部分与是否存在有关GC应该从perm gen中删除旧的Class实例。通常,每次热部署时,都会将新的类实例添加到PermGen内存池中,而现在未使用的旧实例通常不会被删除。默认情况下,Sun JVM不会在PermGen中运行垃圾收集,但可以使用可选的java命令参数启用它。
I believe that part of the problem has to do with whether or not the GC should remove old Class instances from perm gen, or not. Typically, every time you hot deploy, new class instances are added to the PermGen memory pool, and the old ones, now unused, are typically not removed. By default, the Sun JVMs will not run garbage collection in PermGen, but this can be enabled with optional "java" command arguments.
因此,如果您热部署足够多次,你最终将耗尽你的PermGen空间。
Therefore, if you hot deploy enough times, you will eventually exhaust your PermGen space.
如果你的网络应用程序在取消部署时没有关闭完全 - 如果它让线程运行例如 - 然后该Web应用程序使用的所有Class实例都将固定在PermGen空间中。您重新部署,现在将所有这些Class实例的另一个完整副本加载到PermGen中。你取消部署并且Thread继续运行,在PermGen中固定另一组类实例。你重新部署并加载一整套复制副本......最终你的PermGen填满了。
If your web app does not shut down completely when undeployed -- if it leaves a Thread running, for example -- then all of the Class instances used by that web app will be pinned in the PermGen space. You redeploy and now have another whole copy of all of these Class instances loaded into PermGen. You undeploy and the Thread keeps going, pinning ANOTHER set of class instances in PermGen. You redeploy and load a whole net set of copies... and eventually your PermGen fills up.
你有时可以解决这个问题:
You can sometimes fix this by:
- 向最近的Sun JVM提供命令参数,以便在PermGen和类中启用GC。即:
-XX:+ UseConcMarkSweepGC -XX:+ CMSClassUnloadingEnabled -XX:+ CMSPermGenSweepingEnabled
- 使用不同的JVM使用固定大小的PermGen或在加载的类上使用GC
但如果你的网站有用,那么这只会 应用程序完全干净地关闭,不会对该Web应用程序的类加载器加载的任何类的任何类实例保留实时引用。
But this will help only if your web app shuts down completely and cleanly, leaving no live references to any of the Class instances of any Class loaded by the Class loaders for that Web App.
即使这不一定修复问题,因为类加载器泄漏。 (在某些情况下,还有太多的实习字符串。)
Even this will not necessarily fix the problem, due to class loader leaks. (As well as too many interned strings in some cases.)
查看以下链接了解更多信息(两个加粗的图表有很好的图表来说明部分问题) 。
Check out the following links for more (the two bolded ones have nice diagrams to illustrate part of the problem).
- Classloader leaks: the dreaded "java.lang.OutOfMemoryError: PermGen space" exception
- The Unknown Generation: Perm
- Presenting the Permanent Generation
- Tomcat Wiki: How to Deal With Out Of Memory Errors
这篇关于是什么让热部署成为“难题”?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!