堆:内存管理的核心区域,在物理上可以不连续,在逻辑上是连续的
一 堆内存逻辑划分
Java7及以前:
- Young Generation Space:年轻代(新生代,新生区) Young/New 划分为 Eden区和Survivor区
- Tenure Generation Space:老年代(老年代,养老区)Old/Tenure
- Permanent Space:永久代 Perm
java8及以后:
- Young Generation Space:年轻代(新生代,新生区)Young/New 划分为 Eden区和Survivor区
- Tenure Generation Space:老年代(老年代,养老区) Old/Tenure
- Meta Space:元空间 Meta
二 堆空间大小的设置
1.-Xms:表示堆区起始内存,等价于-XX:InitialHeapSize
2.-Xmx:表示堆区最大内存,等价于-XX:MaxHeapSize
3.超过配置的堆区最大内存会报OOM
4.通常会将1,2配成相同的值,目的是为了能在对堆区垃圾回收清理完毕之后,不需要再重新计算堆区的大小,提高性能
5.默认情况:
初始堆内存大小为:(物理计算机内存大小)/64
最大堆内存大小为:(物理计算机内存大小)/4
6.查看设置的参数:
①先jps查看进程id,再jstat -gc 进程id
②-XX:+PrintGCDetails
三 年轻代和老年代
年轻代占1/3堆空间
老年代占2/3堆空间
默认:-XX:NewRatio=2 表示:新老代比例为1:2
eden和另两个survivor比例为8:1:1
默认:-XX:SurvivorRatio=8
(由于自适应内存分配机制的存在:-XX:+UseAdaptiveSizePolicy的存在,单独更改SurvivorRatio可能会不生效)
可使用-Xmn 设置新生代最大内存大小(一般不建议修改此值)
四 堆内存分代过程
过程描述
1.第一次当Eden区满了之后,进行垃圾回收YGC(YoungGC)/Minor GC
2.活着的对象从Eden ——>s0区 年龄计数器age1
3.Eden区再满,把活着的对象从Eden——>s1,年龄计数器age1;把 s0活着的对象——>s1,年龄计数器age1+1 = age2
4.Eden区再满,把活着的对象从Eden——>s0,年龄计数器age1;把s1活着的对象——>s0,年龄计数器age1+1= age2,age2+1 = age3;
5.循环往复
6.当年龄计数器对应的对象到达15(15为默认值,可通过-XX:MaxTenuringThrehold = <N>进行设置)Promotion晋升至老年代。
*每当Eden区满了之后,会连带着s0,s1一起进行垃圾回收,s0和s1区不会单独主动进行垃圾回收。
*s0,s1:复制之后有交换,谁空谁是to
*垃圾回收频率:频繁在新生代;很少在老年代;几乎不在永久区/元空间;
对象分配及YGC主要过程图解
堆空间垃圾回收分类简述
部分收集(Partial收集):
1.Minor GC/YoungGC:只负责新生代(Eden、s0/s1)收集
2.Major GC/Old GC: 只负责老年代的收集(收集效率比Minor GC 10倍以上)
整堆收集:Full GC
混合收集(只在G1回收器中):Mixed GC
五 内存分配原则
1.优先Eden
2.大对象直接分配到老年代(尽量避免使用大对象)
3.长期存活的对象,分配到老年代
4.动态对象对象年龄判断:
如果survivor中,相同年龄的所有对象大小的总和大于survivor空间的一半,年龄大于或等于该年龄的对象可直接进入老年代,无需等到MaxTenuringThreshold阈值
5.空间分配担保:-XX:HandlePromotionFailure,默认为true(第六节具体说)
TLAB
1.包含在Eden空间内,每个线程一份的私有缓存区域。
2.快速分配策略,避免一系列线程安全问题,是内存分配的首选。
3.参数:
-XX:UseTLAB 设置是否开启TLAB
-XX:TLABWasteTargetPercent设置TLAB占Eden空间百分比大小
4.查看:先jps查看进程id;再jinfo -flag UseTLAB 进程id
六 堆空间参数总结
-XX:+PrintFlagsInitial:查看所有参数默认初始值
-XX:+PrintFlagsFinal:查看所有参数的最终设置的值
-Xms:初始堆空间内存(默认物理内存的1/64)
-Xmx:最大堆空间内存(默认物理内存的1/4)
-Xmn:设置新生代的大小(初始值及最大值)
-XX:NewRatio:配置新生代与老年代在对结构中的占比(默认1:2,参数值为2)
-XX:SurvivorRatio:设置新生代中Eden和s0/s1空间比例(默认8:1:1,参数值为8)
-XX:MaxTenuringThreshold:设置新生代垃圾回收的最大年龄(默认15)
-XX:+PrintGCDetials:输出详细的GC处理日志(打印简单日志:①-XX:PrintGC ②-verbose:gc)
-XX:HandlePromotionFailure:是否设置空间分配担保
(此参数决定了Full GC的时机,JDK6及以前此参数可设置,JDK7及这个参数都是true
Minor GC以前,检查老年代最大可用连续空间 是否大于 新生代所有对象的空间
只要 老年代最大可用连续空间 > 新生代总大小 或者 老年代最大可用连续空间 > 历次晋升的平均对象大小
则进行Minor GC 否则 Full GC 慢慢品。。。)
-XX:+DoEscapeAnalyisis:开启逃逸分析
-XX:EliminateAllocations:开启标量替换
-XX:+EliminateLocks:开启同步消除
堆是分配对象的唯一选择吗?(优化)
答:不是
逃逸分析——>如果没有逃逸出方法——>则进行栈上分配:效率高,不需要垃圾回收
1.成员变量的赋值
2.方法的返回值
3.实例引用传递
逃逸分析:-XX:+DoEscapeAnalyisis
同步省略(同步消除):如果一个对象只能被一个线程访问,则可此对象不考虑同步,字节码中省去Synchronize:
-XX:+EliminateLocks
分离对象或标量替换:标量对应聚合两,即不可再分,开启标量替换:-XX:EliminateAllocations