JVM(三) 堆内存的划分

一、学习JVM的目的一般是出现内存异常的时候快速定位问题和性能优化,那么内存是如何分配的就必须的作为基础知识。在上一篇《运行时数据区》中描述的了解到其实线程独占的三部分gc基本不动,在线程共享的两部分方法区gc也是基本动不了。那gc基本唯一会经常操作的就是堆内存。堆内存的大致划分:
JDK 1.8和以前
JVM(三) 堆内存的划分_第1张图片
JDK 1.8以后 不在用永久带,而是Meta Space已经不在堆内存中。
JVM(三) 堆内存的划分_第2张图片
1.1 新生代
所有new的对象都在堆里面。对象优先分配到Eden区,可以通过参数-XX:SurviviorRatio=8来指定Eden区和Survivior的比例,这样划分的依据和好处是根据gc的回收算法来定的。做到了内存利用率高。
经过几次(可以通过参数设置)minor gc还存活的对象进入S0,再经过几次minor gc还存活进入S1,达到minor gc的阈值(-XX:MaxTenuringThreshold=?)进入老年代。
还有就是动态对象年龄判定,相同年龄所有对象的大小总和 > survivor空间的一半,直接晋级老年代,不需要进行年龄阈值的判断。
这个区域的理想是98%以上的对象能够被回收。
1.2 老年代
大对象(-XX:PretenureSizeThreadshold=1024)直接进入老年代,在新生代里面长期存活的对象进入老年代。老年代对应的是major gc。
1.3 永久带
包含元数据信息,如class,method的detail信息

二、空间分配担保(就像贷款一样) -XX:HandlerPromotionFailure
Minor GC之前检查
老年代最大可用连续空间是否 > 新生代所有对象总空间。
大于----> Minor GC
不大于—>老年代最大可用连续空间是否>历次晋升到老年代对象的平均大小
大于-----> Minor GC
不大于 -----> Full GC
-XX:HandlerPromotionFailure
注:Minor GC 是针对新生代的垃圾回收,MajorGC是老年代的,Full GC 是Minor GC 加上 MajorGC

三、对象的创建过程(new的过程)
JVM(三) 堆内存的划分_第3张图片
3.1 怎么在堆中分配内存
a,堆规整的前提下--------> 用指针碰撞
b,堆不规整的 ---------> 用空闲列表
堆规整不规整是由垃圾回收器的策略决定的
3.2 分配内存中线程安全的问题
比如多个线程同时new对象,那指针的位置归谁?
解决办法 1)同步加锁 —效率低
2) 在堆中给每个线程分配区域。
3.3 对象的结构
a, Header:自身运行的数据(很多)
b, InstanceDate 程序员写的
c, Padding
3.4 对象的访问定位
a,使用指针 hotspot 采用
b,使用句柄 (多一步操作,在堆中有句柄池。优点是栈中的地址不会变)

你可能感兴趣的:(JVM)