Java 什么时候调用垃圾收集器

When does Java calls Garbage Collector

我读了很多 post 关于 Java 堆的文章。我看到如果我们得到 java.lang.OutOfMemoryError 我们应该增加 -Xmx 来解决这个问题。

例如

java -Xmx2048m -Xms256m

这会将 Java 使用的堆内存增加到 2048MB。现在来敲打我的头的问题。

参考上述设置的问题:

Java 是否在调用垃圾收集器之前等待其 HEAP space 达到 256MB?这是我们希望 -XMx 和 -Xms 具有相同值的生产原因,以便 Java 在达到最大内存分配之前不调用堆管理吗?

如果有人能在 Xmx 代表最大 java 堆和 Xms 代表最小 java 堆旁边提供一些关于 -Xmx 和 -Xms 的额外细节,我将不胜感激。

-Xms : min heap size. Having -Xms = 1.8GB (32bit) can be bad, because you don't let memory for anything else.

-Xmx : max heap size (ex: -Xmx1024)

更多信息请看这里:Get started with java JVM memory (heap, stack, -xss -xms -xmx -xmn...)

第一个问题的答案是:视情况而定。您可以设置不同的 GC 策略,甚至可以说服 JVM 在堆满之前不 运行 GC,但这通常不是一个好主意。这绝对不是通常发生的事情,相反,堆 divided into several smaller areas 具有不同的用途,GC 是由它们填满触发的。

回答第二个问题:不,那是完全不同的问题。

使用 -Xms256m 时,JVM 将在启动时向操作系统请求 256 兆字节的内存。

如果 运行 用完了,它将要求更多,直到达到 -Xmx 指定的数量。要求 OS 为您的进程分配更多内存需要时间,因此最好避免在服务器上使用,因为在服务器上您几乎可以准确预测有多少内存可用于您的应用程序。

请注意,上述过程仅与 GC 间接相关,GC 仅清除已由 OS 分配给 JVM 的堆。

编辑: 要检查到底发生了什么,您可以使用 -verbose:gc 命令行选项启动 JVM。

垃圾回收发生在各代填满时。

堆上有两个主要代:youngold。新生代又称为new代,或edenspace。老年代又细分为survivor spacetenured generation.

新分配的对象从新生代开始,如果它们在垃圾收集中存活下来,就会被转移到老年代。垃圾收集在年轻一代中运行得更频繁。

这些是你的 Heap Tuning Parameters:

  • -Xms(initial/minimum堆大小,所有代)

  • -Xmx(最大堆大小,所有代)

  • -Xmn(新生代大小,下面-XX:NewSize的替代)

  • -XX:MinHeapFreeRatio=最小值(自由space对生物体的最小期望比例,百分比)

  • -XX:MaxHeapFreeRatio=最大(自由space对活体的最大期望比例,百分比)

  • -XX:NewRatio=ratio(老年代与新生代的比例:默认为2,即2:1,即堆是2/3老一代)

  • -XX:NewSize=大小(initial/minimum新生代大小)

  • -XX:MaxNewSize=size(最大新生代大小)

  • -XX:+AggressiveHeap(初始堆的大小是根据物理内存的大小计算出来的,并尽量为堆使用物理内存)