对象内存分配过程
- 对于栈,对象完成逃逸分析和标量替换后,会存在栈内存中,否则会存在堆中
- 大对象直接进入老年代,大对象可以通过JVM 参数设定大小,-xx:PretenureSizeThreshold
- 对象到达一定年龄,经历过多次minor gc 后可以进入老年代,默认CMS 5次,PS 是15次,-xx:MaxTenuringThreshold,(为什么是15次,因为对象头分配的是4位来储存这个信息,所以最大是15次,设置再大也没用)
- 根据对象动态年龄判断,如果S区中的对象总和超过S区中的50%,那么下一次做复制的时候,把年龄大于等于本次最大年龄的对象一次性全部放入老年代中。(比如,S1是现在收集eden过来的,S2是上次收集用的,先准备将S2 导入S1, 空出S2 接收eden 新minor gc 留下来的对象,如果两个区总和超过50%,当进行复制的时候肯定有一个区会溢出,所以需要进行S区存在的对象送达老年代)
- 老年代空间分配担保机制
老年代空间分配担保机制: 在minor gc时,检查老年代剩余可以空间是否大于年轻代里的所有对象(包含垃圾和非垃圾)。如果大于等于,则做minor gc。如果小于,在看下是否配置了担保参数,-xx: -HandlePromotionFailure, 如果配置了,那么判断老年代剩余空间是否小于历史每次minor gc后进入老年代的对象的平均大小,如果是,进行full goc, 减少一次minor gc。 如果不是执行minor gc. 如果没有任何担保,直接进行full gc.
对象逃逸分析
Test1方法中创建的对象不被返回引用,通过逃逸分析将其创建在栈内存中,随方法弹出栈一并被销毁不需要GC
标量替换
标量:不能被进一步分解的量
* 基础数据类型
* 对象引用
聚合量:可以进一步分解的量
什么是标量替换?
标量替换指: 通过逃逸分析确定该对象不会被外部访问,并且对象可以被进一步分解时,JVM不会创建该对象,而是创建他的成员变量来代替。
如果通过逃逸分析,能够确认对象不会被外部访问,就会在栈上分配对象。
如果在栈上分配对象的话,这个对象占用的空间就会在栈帧出栈的时候被销毁,所以,通过栈上分配可以降低垃圾回收的压力。