判断对象的存活:
引用计数算法
可达性分析
在Java中可作为Gc roots 的对象包括:
1.方法区:类静态属性引用的对象
2.方法区:常量引用的对象
3.虚拟机栈中对象
4.本地方法栈jni中引用的对象
GC是统计学测算出超过98%以上的对象是一次就会被minor gc时回收的。但是我们不能较真的只给 他们留下2%,而是多算一些预留10%,用来存储新生代GC后存活的对象,所以我们GC其实是90%的控件,剩下的10%放在S1区域,然后结束后S1需要放回给S0区,也就是对调,既然能对调其实就是两个区域一般大,(其实对调就是复制算法)。这也是为什么会再有个10%的S0区域出来。这样比例就是8:1:1了(80%:s1:s0=80%:10%:10%=8:1:1)这里的8 和其中的一个 1 合起来供占据90%,GC就是清理的他们,始终保持着其中一个 1 区是空留的,保证GC的时候复制回收的对象有个存储的地方。
具体来说
首先 堆= eden+ from +to eden:from:to=8:1:1 默认会这样
当对象在 Eden ( 包括一个 Survivor 区域,这里假设是 from 区域 ) 出生后,在经过一次 Minor GC 后,如果对象还存活,并且能够被另外一块 Survivor 区域所容纳,则使用复制算法将这些仍然还存活的对象复制到另外一块 Survivor 区域 ( 即 to 区域 ) 中,然后清理所使用过的 Eden 以及 Survivor 区域 ( 即 from 区域 ),并且将这些对象的年龄设置为1,然后再将通区域中的对象复制到from 中(所以这里解释了为啥要1:1),然后再次同上,以后对象在 Survivor 区每熬过一次 Minor GC,就将对象的年龄 + 1,当对象的年龄达到某个值时 ( 默认是 15 岁,可以通过参数 -XX:MaxTenuringThreshold 来设定 ),这些对象就会成为老年代。
但这也不是一定的,对于一些较大的对象 ( 即需要分配一块较大的连续内存空间 ) 则是直接进入到老年代。
还有 当代码中调用 System.gc() 对于可达的对象会提前进入老年代,并且 这个方法先minor gc 然后在 full gc。