堆参数对 GC/性能的影响?

emi*_*lly 2 java garbage-collection memory-management heap-memory

网上的大部分地方,我得到以下有关堆参数的信息

-Xms<size> set initial Java heap size -Xmx<size> set maximum Java heap size

这是我提到-Xms 512M -Xmx 2048M参数时的理解/问题,

-Xms :-我的理解是,如果我的 java 进程实际上只需要 200M ,提到 -Xms 512M ,java 进程仍将只分配 200M(需要实际内存)而不是 500M 。但是,如果我已经知道我的应用程序将在启动时占用这 512M 内存,那么指定小于会对性能产生影响,因为无论如何需要调整堆块大小,这是一项代价高昂的操作。

根据与我的同事的讨论,默认情况下 GC 将在 Xms 值的 60% 上触发。那是对的吗 ?如果是,是依赖 Xms 值的次要 GC 还是完整 GC?

Xms 更新:- 在读取JVM 堆参数后这似乎是正确的,但默认情况下值再次为 60%,它是依赖于 Xms 值的次要 GC 还是完整 GC?

-Xmx:-我的理解是提到了 -Xmx 2048M ,java 进程实际上会保留 2048M 内存供操作系统使用,这样另一个进程就无法获得它的份额。如果 java 进程无论如何需要超过 2048M 的内存,那么内存不足会被抛出。

此外,我相信 Full GC 触发器与 -Xmx 的值存在某种关系。因为我观察到的是当内存接近 Xmx 的 70% 时,jconsole 中会发生 Full GC。那是对的吗?

配置:-我正在使用 linux box(64 位 JVM 8)。默认 GC,即并行 GC

Dee*_*akV 5

GC 不会仅基于 Xms 或 Xmx 值触发。

Heap = New + Old generation
堆大小(最初设置为 Xms)分为 2 代 - New(又名 Young)和 Old(又名 Tenured)。默认情况下,新生代是总堆大小的 1/3,而老年代是堆大小的 2/3。这可以通过使用名为 NewRatio 的 JVM 参数进行调整。其默认值为 2。

Young Generation 进一步划分为 Eden 和 2 Survivor 空间。这3个空格的默认比例为:3/4th、1/8th、1/8th。

旁注:这是关于并行 GC 收集器的。对于 G1 - 新的 GC 算法以不同的方式划分堆空间。

Minor GC 所有新对象都分配在 Eden 空间中(海量对象除外,它们直接存储在老年代)。当 Eden 空间变满时,会触发 Minor GC。在多个次要 GC 中幸存下来的对象被提升到老年代(默认为 15 个周期,可以使用 JVM 参数:MaxTenuringThreshold 进行更改)。

Major GC 与并发收集器不同,Major GC 是根据已用空间(默认为 70%)触发的,并行收集器根据下面提到的 3 个目标计算阈值。

并行收集器目标

  • Max GC pause time - 执行 GC 所花费的最长时间
  • 吞吐量 - GC 与应用程序花费的时间百分比。默认 (1%)
  • 占用空间 - 最大堆大小 (Xmx)

因此,默认情况下,Parallel Collector 尝试在垃圾收集中花费最多 1% 的总应用程序运行时间。

更多细节在这里

Xms 到 Xmx
在启动期间 JVM 创建大小为 Xms 的堆,但保留额外空间 (Xmx) 以便以后能够增长。该保留空间称为虚拟空间。请注意,它只是保留空间而不提交。

2 个参数决定堆大小何时在 Xms 和 Xmx 之间增长(或缩小)。

  • MinHeapFreeRatio (default: 40%) : 一旦空闲堆空间低于 40%,就会触发 Full GC,堆大小增加 20%。因此,堆大小可以不断增加,直到达到 Xmx。
  • MaxHeapFreeRatio(默认值:70%):另一方面,堆可用空间超过 70%,然后在每次 GC 期间堆大小逐渐减小 5%,直到达到 Xms。

这些参数可以在启动时设置。在这里这里阅读更多关于它的信息

PS:JVM GC 是一个有趣的话题,我建议阅读这篇优秀的文章以深入了解。可以在此处找到所有 JVM 调整参数。