首页 > 代码库 > JVM heap中各generation的大小(Sizing the Generations)
JVM heap中各generation的大小(Sizing the Generations)
以下是对Java8官方文档 https://docs.oracle.com/javase/8/docs/technotes/guides/vm/gctuning/sizing.html 这篇的翻译
=============
jvm初始化时, 会将-Xmx指定大小的内存空间预留, 如果-Xms小于-Xmx, 那么不会立即将所有空间给jvm, 未给予的部分为"virtual", 留给堆(heap)中的不同部分(老年代tenured generation和年轻代young generation)将来增长后在需要时使用.
参数NewRatio是老年代相对于年轻代的比例
整个堆(Total heap)
以下关于heap大小增长和收缩的讨论不适应于 parallel collector, 但是控制heap和各个generation的大小的参数, 对parallel collector是同样有效的
在默认情况下, jvm会在每次垃圾回收后增长或收缩heap大小, 以便保持合适比例的空闲空间. 这个百分比由-XX:MinHeapFreeRatio=<minimum> and -XX:MaxHeapFreeRatio=<maximum>来设定. 而整个heap的最小和最大尺寸, 由-Xms<min> 和 -Xmx<max>设定.
例如对于MinHeapFreeRatio = 40, MaxHeapFreeRatio = 70, 当一个generation的可用空间小于40%, 则这个generation会增长空间以保持40%的可用空间, 直到达到这个generation允许的最大空间. 同样的, 如果空闲空间大于70%, 那么这个generation会收缩以保持只有70%的可用空间, 直到这个generation允许的最小空间.
在未设定的情况下, 默认的最大heap空间是由jvm计算得到的, 用于parallel collector的java se和服务器jvm的所有的垃圾回收器都使用同样的算法. 对于上限大小的计算, 在32位和60位机器上不同, 而客户端jvm采用的算法是一样的, 其得到的最大heap大小要小于服务器jvm.
对于服务器应用的heap大小, 有以下原则
1. 除非你对暂停有问题, 给jvm设置尽可能多的内存, 默认的大小远远不够
2. 将-Xms和-Xmx设置为一样的可以避免jvm做heap大小决策, 当然如果你设置的不合适, jvm也不能自己再做调整
3. 一般来说, 在增加处理器核数时也增加内存, 内存分配是可以同步处理的
年轻代 The young generation
除了设置总内存大小外, 对垃圾回收性能影响最大的因素就是给年轻代配置的heap比例. 年轻代设置的越大, 小回收(minor collection)的频率就越低. 不过, 对于给定的heap尺寸, 一个大的年轻代意味着一个小的老年代(tenured generation), 这会增加主回收(major collection)的频率. 最优的配置取决于应用内对象的生命周期分布.
默认情况下, 年轻代的大小由NewRatio决定, 例如-XX:NewRatio=3意味着年轻代和老年代的比例为1:3, 换句话说, 伊甸区和幸存区(eden + survivor, 即e + s0 + s1)将占整个heap大小的1/4.
参数NewSize和MaxNewSize规定了年轻代大小的范围, 将其设置为同样的值, 就固定了年轻代的大小. 这对于调解年轻代的合适大小有帮助.
幸存区 Survivor Space Sizing
可以用SurvivorRatio来调解幸存区的大小, 但是一般来讲这个对性能没多大影响. 例如-XX:SurvivorRatio=6设置了幸存区和伊甸区的比例为1:6, 换句话说, 每个幸存区(有两个)大小都是伊甸区的1/6, 而占整个年轻代的1/8
如果幸存区的空间太小, 如果有一部分对象在YGC中幸存下来, 幸存区只有很少空间容纳这些对象, 结果大部分幸存对象在一次GC后,就会被转移到老年代, 这就不是我们期望的. 而如果幸存区的空间太大, 空闲的空间就是浪费. 在每次垃圾回收时, jvm会选择一个阈值, 即某个对象被移入老年代前要经历的回收次数. 这个阈值取决于是否可以将幸存区保持50%可用空间. 参数 -XX:+PrintTenuringDistribution 可以用于显示这个阈值以及各年轻代对象的年龄, 这对于获取应用的对象的生命周期分布特别有用.
对于默认的jvm设置, 年轻代的大小取决于整个heap大小和NewRatio的值, 而MaxNewRatio默认是not limited
对于服务器应用, 一般的设置原则是
1. 首先确定你能给jvm提供的最大的内存大小, 然后再配置年轻代的大小以得到最佳性能
注意: 最大的内存大小不要超过机器实际安装的内存大小
2. 如果jvm的heap大小是固定的, 那么老年代和年轻代的内存大小是互相制约的, 需要保证老年代的内存大小足够用于容纳任何时候应用运行所需要的数据, 在这个基础上增加10%到20%的冗余度.
3. 基于上一条对老年代内存大小的要求
3.1 尽可能给予年轻代足够的内存
3.2 在增加cpu核数时增加内存, 因为内存分配是可以并行的
============
另外可以参考的文章: https://blog.codecentric.de/en/2012/08/useful-jvm-flags-part-5-young-generation-garbage-collection/ 对应的中文翻译 http://weiboxie.iteye.com/blog/2085054
.
JVM heap中各generation的大小(Sizing the Generations)