我监控了一个Java7应用程序几周,我观察了一些我想了解的事情。
从应用程序开始,总加载类的数量不断增长,我认为这是正常的,因为应用程序(基于netty 3.6库)每小时打开和关闭很多tcp连接。我不认为我也应该担心这一点因为当前的类加载计数器没有增长。
我无法理解的是为什么大约每7天,总加载类的数量会下降到当前类加载的计数器。此外,堆内存使用情况似乎遵循相同的模式:堆空间增长到70mb,然后减少到20mb。
就像每7天执行更多“更深入”的垃圾收集器一样。
应用程序从未重新启动。
有人可以解释一下这种行为吗?感谢。
P.S。 不幸的是我无法截取JConsole的截图。
答案 0 :(得分:3)
在Oracle JVM中,堆中有多个内存池。其中一个是旧的游泳池,另一个是烫发池。旧的gen池包含在几个垃圾收集中幸存下来的对象。 perm gen池包含加载的类和其他“永久”数据。
堆池的垃圾收集方式不同。您看到的标准垃圾收集通常在eden池上运行,而eden池是新创建的对象所在的位置。理论上说,如果你有很多短期对象,那么这些对象通常可以在一小堆中进行垃圾收集。与此同时,您的长寿命对象会被提升到较旧的池中,并且收集频率较低。
这一切都是为了允许更有效的垃圾收集,因为长寿命对象不像短期对象那样经常被考虑收集。因此,您所看到的“更深层次”执行可能是在收集旧的Gen池时。事实上,Oracle决定实施一些东西,以便perm gen池与旧的gen池同时收集垃圾,这就是为什么它们同时掉落的原因。
最后,简单地打开和关闭TCP连接不应该导致新类被加载。可能发生的是一些库在连接到达时创建新的动态代理。这个动态代理是一个在运行时创建的全新类,当它被创建时,它将增加你的总类加载次数。
参考文献:
In Java is Permanent Generation space garbage collected?
Java 6 garbage collection details(来自Oracle)