1

当我使用 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 个,不包括

代码缓存(非堆内存)。

我想知道为什么垃圾收集器从来没有运行过

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

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

有没有同样的意义?

4

2 回答 2

3

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

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

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

除方法区外,Java 虚拟机实现可能需要内存用于内部处理或优化,这也属于非堆内存。例如,JIT 编译器需要内存来存储从 Java 虚拟机代码转换而来的本地机器代码,以实现高性能。

你问什么属于非堆内存?

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

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

于 2012-05-08T06:32:47.230 回答
0

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

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

于 2014-10-14T09:39:33.923 回答