Java堆行为

时间:2013-02-19 23:25:05

标签: java oracle memory jvm heap

给出如下的

之类的java内存配置
 -Xmx2048m -Xms512m

当内存使用量增加超过512米时,VM的行为是什么?是否有一个特定的算法?即。它是直接达到最大值,它是否加倍,它是以增量为单位,还是仅在需要内存时分配?手术有多贵?

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

3 个答案:

答案 0 :(得分: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

(操作类型的“费用”取决于操作系统以及正在发生的其他事情。如果系统被加载并且操作系统必须进行一些交换以为您创建连续的内存块,那么它可能非常昂贵!)

答案 1 :(得分: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]

以上摘自官方document

  

在这里,我们看到两个小集合,后面跟着一个主要集合。   箭头前后的数字(例如,325407K->83000K来自   第一行)表示之前和之前的活动对象的组合大小   垃圾收集后,分别。经过小小的收藏   size包括一些垃圾(不再存在)的对象但是   无法回收。这些对象要么包含在终身职位中   生成,或从终身或永久世代中引用。

     

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

     

该行的最后一项(例如0.2300771 secs)表示时间   采取执行收集;在这种情况下大约四分之一   一秒钟。

     

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

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

答案 2 :(得分:0)

需要注意的是,JVM on Initialization实际上保留了最大地址空间,但没有分配物理内存。通常,JVM会为Old和Young一代分配空间。年轻一代有中间空间。调用的新对象包含在Young Generation中。

当填充中间空间时,调用GC,将参考对象移动到Young Generation Segment中称为Survivor Space的中间空间之一。 GC可以通过保存线程的状态算法或算法来跟随“停止世界”,以便进程继续运行(?)。

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