Permgen和垃圾回收Java,打破Permgen的谣言

3
我知道在JVM中,permgen区域用于存储类定义。在我的Tomcat中,我看到permgen的当前内存使用量接近100MB,似乎它随着时间的推移而不断增长,即使没有人使用Tomcat中的应用程序。
我的问题是: permgen永远不会被垃圾回收吗?我的意思是那里使用的内存会不断增长吗?
当permgem被垃圾回收时是什么情况?
“CMSPermGenSweepingEnabled”和“CMSClassUnloadingEnabled”是什么意思?
我的permgem的最大大小为256,我不想在下周遇到OutMemoryException。
请只提供准确和有文献支持的答案。
我使用Tomcat 7,Java 7,经常使用并行部署技术,并且每周进行多次取消部署和重新部署。我从不使用字符串的intern()方法。

你正在使用哪个版本的Tomcat? - Claudiu
你是否过多地内部化了String对象? - jmj
由于您的PermGen占用量目前仅为最大值的一半以下,垃圾收集器可能尚未被触发。 - Marko Topolnik
“CMS…” 选项与并发标记和清除收集器有关,该收集器不是默认开启的。如果没有开启,则这些设置所暗示的操作会作为例行事项发生。 - Marko Topolnik
@Marko Topolnik,请记录下你的第一条评论:提供一些支持你说法的链接或书籍。 - Nestor Hernandez Loli
显示剩余3条评论
1个回答

2
实际上,Permgen并非永远不会被垃圾回收。它包含应用程序加载的类,并在类加载器被垃圾回收时进行回收,通常在重新部署场景中发生。
您可以使用以下JVM标志查看类何时加载到Permgen中,并从其中卸载:
-XX:+TraceClassLoading -XX:+TraceClassUnloading

使用以下标志查看已加载的类:
-verbose:class

如果应用程序反射密集,那也可能是一个原因,请查看这个 答案,尝试使用 visualvm 获取堆转储并查找名为 sun.reflect.GeneratedMethodAccessor11 的类。
关于垃圾回收标志,请参考这个 答案,但修复permgen泄漏的最佳方法是使用一些工具/日志来查看正在创建哪些类以及为什么要创建。

需要注意的是,根据你询问的人和你所谈论的JVM版本,“permgen”可能包括在启动时分配且无法被收集的内容。根据JVM/收集器的版本,这可能会与“permgen”中的类对象一起抛出,或者可能会被物理上或“道德上”单独处理。 - Hot Licks

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接