9

给定如下的 java 内存配置

 -Xmx2048m -Xms512m

当内存使用量增加到超过 512m 时,VM 的行为是什么?它是否遵循特定的算法?IE。它是直接达到最大值,是加倍,还是递增,还是只在需要内存时分配?手术有多贵?

我正在专门研究 Oracle/Sun JVM 1.6 版。我认为这在某处的 Oracle 网站上有记录,但我找不到它。

4

3 回答 3

6

决定何时需要调整大小是垃圾收集器的工作,因此它由 GC 参数“MinFreeHeapRatio”决定。如果 GC 需要更多空间,它将增长到该值指定的堆百分比可用的大小。

现代平台上的典型值是 40ish,所以如果您从 512MB 开始并且有不到 40% 的可用空间,这意味着您超过了 ~308MB,它将增加直到 40% 再次可用。所以说收集后仍有 400MB 的活动对象,你的堆将上升到 ~667MB。(是的,它被命名为比率,但需要一个 % 值作为参数......搜索我!)

请注意,这有点不准确,垃圾收集器是“分代的”,实际上可以调整各个代的大小,但它也有代大小之间的强制比率,如果您的对象以大致估计的方式分布在长寿命和短寿命之间,它非常适合信封背面。

这适用于 Java 6 中的默认设置。如果您使用自定义垃圾收集器配置,它可能会有所不同。你可以在这里阅读:http ://www.oracle.com/technetwork/java/javase/gc-tuning-6-140523.html#generation_sizing.total_heap

(操作的“费用”取决于操作系统和其他情况。如果系统被加载并且操作系统必须进行一些交换来为您创建一个连续的内存块,那么它可能是非常贵!)

于 2013-02-19T23:33:00.933 回答
2

使用-verbose:gc和/或-XX:+PrintGCDetails选项应该会给你更多的细节。

-verbose:gc这是一个打开选项的示例输出:

[GC 325407K->83000K(776768K), 0.2300771 secs]
[GC 325816K->83372K(776768K), 0.2454258 secs]
[Full GC 267628K->83769K(776768K), 1.8479984 secs]

以上内容来自官方文档的解释:

在这里,我们看到两个次要集合,然后是一个主要集合。箭头前后的数字(例如,325407K->83000K从第一行开始)分别表示垃圾回收前后活动对象的组合大小。在次要收集之后,大小包括一些垃圾(不再存在)但无法回收的对象。这些对象要么包含在永久代中,要么从永久代或永久代中引用。

括号中的下一个数字(例如,776768K第一行中的 ( ) )是堆的提交大小:Java 对象在不向操作系统请求更多内存的情况下可用的空间量。请注意,此数字不包括幸存者空间之一,因为在任何给定时间只能使用一个,也不包括永久代,其中包含虚拟机使用的元数据。

行中的最后一项(例如0.2300771 secs)表示执行收集所花费的时间;在这种情况下,大约是四分之一秒。

第三行主要集合的格式类似。

以这种方式运行应用程序并更新最小和最大堆大小可以很好地了解 VM 的堆分配和垃圾收集模式。

于 2013-02-19T23:40:55.473 回答
0

需要注意的是,初始化时的JVM实际上保留了最大的地址空间,但不分配物理内存。通常,JVM 会将空间分配给老年代和年轻代。新生代中有中间空间。调用的新对象包含在年轻代中。

当中间空间被填满时,调用 GC 将引用对象移动到年轻代段中称为幸存者空间的中间空间之一。GC 可能会通过保存线程的状态算法或算法来遵循“stop-the-world”,以便进程继续运行(?)。

当 Survivor 空间填满时,JVM 会调用完整的 GC。

于 2013-02-20T00:31:45.480 回答