当我使用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内存池中垃圾收集对象?
这有什么意义吗?
答案 0 :(得分:3)
阅读MemoryMXBean的文档。特别是关于非堆内存:
的部分Java虚拟机管理堆以外的内存(参考 作为非堆内存)。 Java虚拟机有一个方法区域 在所有线程之间共享。方法区域属于非堆 记忆。它存储每类结构,例如运行时常量 池,字段和方法数据,以及方法和代码 构造函数。它是在Java虚拟机启动时创建的。
方法区域在逻辑上是堆的一部分,但是是Java虚拟的 机器实现可以选择不垃圾收集或 压缩它。类似于堆,方法区域可能是固定的 大小或可能扩大和缩小。方法区域的内存 不需要连续。
除方法区域外,还有Java虚拟机实现 也可能需要内存进行内部处理或优化 属于非堆内存。例如,JIT编译器需要 用于存储从Java翻译的本机机器代码的内存 高性能的虚拟机代码。
你问的是什么属于非堆内存?
永久生成:包含虚拟机本身的所有反射数据的池,例如类和方法对象。对于使用类数据共享的Java VM,这一代将分为只读区域和读写区域。
代码缓存:HotSpot Java VM还包含一个代码缓存,其中包含用于编译和存储本机代码的内存。
答案 1 :(得分:0)
代码缓存是一个非堆空间,它是垃圾收集的,但不是普通的GC线程。相反,它是由JIT的帮助程序线程收集的,因此它不会以与其他内存池显示相同的方式显示出来。不幸的是,代码缓存MXBean不支持通知,因此您不得不轮询或提出另一种方法来监控内存使用情况。
总而言之,总内存使用量可能无济于事,因为代码缓存中的代码blob无法移动,这意味着代码缓存无法被压缩。因此,您可能拥有大量内存,但如果它有碎片,您仍然可能会遇到分配失败,如果JIT线程无法正确清理缓存,将导致JIT关闭。它在JVM的生命周期内不会重新启动。