垃圾收集未运行代码缓存内存池

时间:2012-05-08 06:01:52

标签: java memory garbage-collection jvm-hotspot

当我使用GarbageCollectorMXBean打印垃圾收集的详细信息时,输出显示以下信息: -

Name: PS ScavengeCollection 
count: 72
Collection time: 3041
Memory Pools:   PS Eden Space   PS Survivor Space

Name: PS MarkSweepCollection 
count: 5
Collection time: 4922
Memory Pools:   PS Eden Space   PS Survivor Space   PS Old Gen 

现在,ScavengeCollection和MarkSweep集合涵盖5个可用内存池中的4个,不包括

  

代码缓存(非堆内存)。

我想知道为什么Garbage Collection从未运行

  

由CodeCacheManager内存池管理的代码缓存内存池。

这是否意味着GC永远不会从CodeCacheManager内存池中垃圾收集对象?

这有什么意义吗?

2 个答案:

答案 0 :(得分:3)

阅读MemoryMXBean的文档。特别是关于非堆内存:

的部分
  

Java虚拟机管理堆以外的内存(参考   作为非堆内存)。 Java虚拟机有一个方法区域   在所有线程之间共享。方法区域属于非堆   记忆。它存储每类结构,例如运行时常量   池,字段和方法数据,以及方法和代码   构造函数。它是在Java虚拟机启动时创建的。

     

方法区域在逻辑上是堆的一部分,但是是Java虚拟的   机器实现可以选择不垃圾收集或   压缩它。类似于堆,方法区域可能是固定的   大小或可能扩大和缩小。方法区域的内存   不需要连续。

     

除方法区域外,还有Java虚拟机实现   也可能需要内存进行内部处理或优化   属于非堆内存。例如,JIT编译器需要   用于存储从Java翻译的本机机器代码的内存   高性能的虚拟机代码。

你问的是什么属于非堆内存?

永久生成:包含虚拟机本身的所有反射数据的池,例如类和方法对象。对于使用类数据共享的Java VM,这一代将分为只读区域和读写区域。

代码缓存:HotSpot Java VM还包含一个代码缓存,其中包含用于编译和存储本机代码的内存。

答案 1 :(得分:0)

代码缓存是一个非堆空间,它是垃圾收集的,但不是普通的GC线程。相反,它是由JIT的帮助程序线程收集的,因此它不会以与其他内存池显示相同的方式显示出来。不幸的是,代码缓存MXBean不支持通知,因此您不得不轮询或提出另一种方法来监控内存使用情况。

总而言之,总内存使用量可能无济于事,因为代码缓存中的代码blob无法移动,这意味着代码缓存无法被压缩。因此,您可能拥有大量内存,但如果它有碎片,您仍然可能会遇到分配失败,如果JIT线程无法正确清理缓存,将导致JIT关闭。它在JVM的生命周期内不会重新启动。