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

.

时间: 2024-11-22 20:35:03

JVM heap中各generation的大小(Sizing the Generations)的相关文章

Java虚拟机(JVM)中的内存设置详解

在一些规模稍大的应用中,Java虚拟机(JVM)的内存设置尤为重要,想在项目中取得好的效率,GC(垃圾回收)的设置是第一步. PermGen space:全称是Permanent Generation space.就是说是永久保存的区域,用于存放Class和Meta信息,Class在被Load的时候被放入该区域Heap space:存放Instance. GC(Garbage Collection)应该不会对PermGen space进行清理,所以如果你的APP会LOAD很多CLASS的话,就很

JVM Heap认知

一.JVM Heap分为三部分:新生代.老年代.永久代: 新生代:用于存放JVM新分配的java对象: 老年代:新生代中经过垃圾回收没有回收掉的对象将被copy到老年代: 永久代:存放Class.Method元信息,也就是反射对象,一般设置为128M足够,设置原则是预留30%空间. 二.GC的引发: 1.新生代拥有2个线程: (1)当新生代的Eden代满了引发普通GC,仅仅回收新生代: (2)新生代空间不足时,会把存活的对象转移到老生代. 2.老年代:当老年代满时引发Full GC,它将会同时回

Eclipse中如何更改字体大小?

Eclipse中如何更改字体大小? 2012-02-06 21:19风吹过云散了- | 浏览 40980 次 wiondow--preferences--general--appearance--colors and fonts--java--java editor text font 然后点change,在弹出的框里选字号,然后确定就可以了~~ 如图!根本没有chage按钮啊?双击也没反映!求解...急!!! 分享到:

Mac中显示文件夹的大小

一.在Finder中查看文件夹大小: 1.Cmd+A选中当前目录下所有文件 2.在右键菜单中选择"显示选项"或者按Cmd+J快捷键 3.选择"计算所有大小"的复选框 然后文件夹的大小就会显示出来了. 参考:http://osxdaily.com/2011/04/05/show-folder-sizes-in-mac-os-x-list-view/ 二.在Terminal中查看当前目录下所有文件(包含文件夹)大小: du -hs * 或者: du -shc * 第二个

JAVA线程池中队列与池大小的关系

JAVA线程中对于线程池(ThreadPoolExecutor)中队列,池大小,核心线程的关系写出自己的理解: 1:核心线程:简单来讲就是线程池中能否允许同时并发运行的线程的数量 2:线程池大小:线程池中最多能够容纳的线程的数量. 3:队列:对提交过来的任务的处理模式. 对于线程池与队列的交互有个原则: 如果队列发过来的任务,发现线程池中正在运行的线程的数量小于核心线程,则立即创建新的线程,无需进入队列等待.如果正在运行的线程等于或者大于核心线程,则必须参考提交的任务能否加入队列中去. 1:提交

Android中如何设置字体大小

在本文中,我们将介绍一些简单的处理方式,帮助开发人员轻松编写出能够应对各类设备型号的应用程序文本方案,同时为用户提供自定义文字尺寸功能.别担心,整个过程没什么难度,只要一步步按指南进行操作,大家再也不用为调整显示效果而劳心伤神了. 在这篇上手教程中,我们将讨论一些实用性步骤,指引开发人员在拥有足够灵活性的前提下保证文字清晰易读,同时使自己的产品能够适应多种屏幕类型及各类用户显示设定. 用户如何按需求配置字体设定 首先要强调一点,某些用户可能存在视力障碍甚至几近失明,他们无法顺利阅读一般尺寸下的文

Java中计算对象的大小

一.计算对象大小的方法 Java中如何计算对象的大小呢,找到了4种方法: 1.java.lang.instrument.Instrumentation的getObjectSize方法: 2.BTraceUtils的sizeof方法: 3.http://yueyemaitian.iteye.com/blog/2033046中提供的代码计算: 4.https://github.com/mingbozhang/memory-measurer提供的工具包: 本质上java.lang.instrument

SQL Server 查看数据库在数据缓存(data cache)中占用的空间大小

1 use master 2 go 3 select * from sys.dm_os_buffer_descriptors 4 go 5 6 --查看数据库在数据缓存(data cache)中占用的空间大小 7 --由于每个数据页对应动态管理视图(dynamic management view,DMV)中的一行,为128 字节,为1/8个千字节(KB) 8 --1字节(Byte)=8位(Bit) 9 --1千字节(KB)=1024字节(Byte) 10 --1兆(MB)=1024千字节(KB)

获取屏幕高宽,在代码中设置控件大小的方法

获取屏幕高宽的方法: 1 import android.view.Display; 2 import android.view.WindowManager; 3 WindowManager windowManager = getWindowManager(); 4 Display display = windowManager.getDefaultDisplay(); 5 if(display.getWidth()==480 && display.getHeight()== 272 ||