31.对象分配内存过程概述
1.对象分配内存过程概述
对象分配内存过程概述,如下图所示:
图中绿色和红色的长方形都是表示的一个个对象。
1.new
出来的对象都是先放着伊甸园区
2.伊甸园区是有大小的,当创建的对象占满了伊甸园区的时候,就会触发YGC/Minor GC
。(YGC=Young GC)
。此时用户线程会停止。垃圾回收器会判断谁是垃圾谁不是垃圾,不被任何对象所引用的对象就是垃圾,垃圾会被销毁(图中红色的长方形表示的是垃圾对象,会被销毁);不是垃圾的对象(绿色长方形)会被移动到S0
区(为什么放在S0
区?在执行GC的时候S0
和S1
谁是空,就会把Eden
区中还要被使用的对象放到哪个区。这时候S0
和S1
都是空,就直接放在S0
。空的那个区称为to
区,另一个就称为from
区,to
区表示的是下一次GC
的时候,伊甸园区的对象往哪里放,下一次GC
,伊甸园区的对象往to
区放)。
3.每一个对象有一个年龄计数器(age)
,从伊甸园区过来的对象age
会被赋值为1。这时候,Eden
区就被清空了。
4.继续new
对象,对象会继续先被放到伊甸园区。同理,如果伊甸园区满了,就会触发YGC/Minor GC
。垃圾对象会被回收(红色长方形),要使用的对象(绿色长方形)会被放到S1
区(注意这里是被放到了S1
区。为什么放在S1
区?在执行GC
的时候S0
和S1
谁是空,就会把Eden
区中还要被使用的对象放到哪个区。这时候S1
是空,就直接放在S1
。空的那个区称为to
区,另一个就称为from
区)。
5.同时,S0
区的对象也会进行判断,是不是垃圾,不是垃圾的话会被放到S1
区(图中S0
中绿色长方形表示的两个对象都不是垃圾,它们会被放到S1
区),对象的age
会加1
变成2
。
6.这时候,伊甸园区和S0
区是空的。当继续new
对象,同理,当伊甸园区满的时候,又会触发GC
,这时候伊甸园区中不是垃圾的对象会被放到S0
区(因为S0
区是空的),垃圾对象会被回收,同时,会检查S1区中的对象是不是垃圾,如果是垃圾,就被回收,不是垃圾就会被放到S0
区,同时对象的age
加1
。
7.这时候,伊甸园区和S1
区又成为了空。继续new
对象,上面的过程会一直进行下去,对象的age
会一直加1
.当age
的值达到15
的时候,就会出现promotion
晋升,Survivor
区中的对象会被放到老年代中。15
是默认的值,可以通过-XX:MaxTenuringThreshold=<N>
进行设置。
注意:
1.当伊甸园区满的时候,才会触发YGC/Minor GC
。S0
区或者S1
区满的时候是不会触发GC
的。
2.S0
区或者S1
区不触发GC
,不代表它们没有GC
。当伊甸园区满的时候,触发的GC
也会对S0
区或者S1
区进行垃圾回收。
总结:
1.对于S0
区和S1
区,它们直接的对象会存在从一个区复制到另一个区的过程,复制完成之后,为空的那一个区称为to
区。
2.对于垃圾回收,频繁发生在新生代,很少发生在老年代,几乎不在永久代/元空间。绝大部分对象在YGC/Minor GC
阶段都被回收了,也就是在伊甸园区、S0
区、S1
区(这三个组成新生代)被回收了。
2.对象分配内存的特殊情况
问题:
如果S0
区或者S1
区满了怎么办?有没有可能对象new
出来直接到了老年代(答案是可能)?有没有可
能S0
区或者S1
区中的对象的age
没有达到15
这个阈值的时候,直接晋升到老年代(可能)?
参考下面对象分配的特殊情况。
1.新创建的对象,会先放到Eden
区,如果Eden
区放得下,就直接放在里面。
2.如果放不下,就会触发YGC
。
3.在YGC
之后,Eden
区变成了空,这时候会存在两种情况,一种是Eden
能够放下新的对象,那么就直接放到Eden
区;如果还是放不下(是一个超大对象,对象的大小甚至超过了Eden
区的大小),这时候就会尝试直接将新对象放到老年代。
4.如果老年代放得下,就会直接放在老年代;如果放不下,就会触发FGC(Full GC)
。FGC
会回收老年代的空间。
5.如果回收之后,老年代能够放得下新对象,就直接放到老年代;如果还是放不下,就会出现OOM
。
6.同时,在YGC
的时候,会去回收S0
区和S1
区的空间,然后会将Eden
区没有被回收的对象,放到S0
区或S1
区。这个时候又会出现两种情况,如果S0
区或者S1
区放得下从Eden
区过来的对象,那么直接放入;如果放不下,Eden
区的对象就会直接晋升到老年代。同样,S0
区或者S1
区对象的age
超过阈值之后,也会晋升到老年代。