可回收对象的判定
判断一个对象是否可回收对象,有两种典型方法:
(1)引用计数法: 简单高效, 容易有循环引用
(2)可达性分析算法:即从GC Roots作为起点,向下搜索它们引用的对象,生成一棵引用树,树的节点视为可达对象,反之视为不可达。
Java语言定义了如下GC Roots对象(每种具体实现对GC Roots有不同的定义):
虚拟机栈(帧栈中的本地变量表)中引用的对象。
方法区中静态属性引用的对象。
方法区中常量引用的对象
本地方法栈中JNI引用的对象
垃圾回收算法
1.复制算法:将可用内存按容量划分为大小相等的两块,每次只使用其中的一块。当这一块的内存用完了,就将还存活着的对象复制到另外一块上面,然后再把已使用的内存空间一次清理掉。
特点:简单高效无碎片, 内存利用率只有一半
2.标记清除算法:先标记可回收对象,然后统一清除。
特点: 效率不稳定;容易产生碎片,导致提前gc。 不适合朝生夕死的新生代,适合于老年代。
3. 标记整理算法:标记要清除的对象不是直接回收, 二是将存活对象都向一端移动,然后清理掉端边界以外的内存。
特点: 对象移动、引用更新比较耗时,效率较低,但无内存碎片。
一次完整GC流程
(1)对象优先在新生代eden区分配
(2)大对象直接进入老生代
(3)新生代使用复制算法进行垃圾回收时,实际不是1:1分成两块,而是8:1:1分成eden、from、to三块。因为绝大部分对象都会被快速回收,需要进入from或to空间的不多。之所以有from、to两个小块,是因为部分对象可能在进入老生代前多次gc都不释放,那2次gc、3次gc就可以在from和to块中进行复制移动。
(4)新生代会在退出Activity5到6秒就触发gc; 老生代仅在内存不足时释放。