背景
功耗大数据打点的过程中,我定义了一个静态全局变量如下:
private static IMiCharge mIMiCharge = IMiCharge.getInstance();
同事提了一句当对象被GC回收之后就会为空,这边先说一下结果此对象是不会被GC回收的,那么接下来我们就一起来看下GC的过程。
判断是否要被GC回收的标准——GCROOT
什么是GC Root
首先我们知道标记算法,JVM的标记算法我们可以了解为一个可达性算法,所以所有的可达性算法都会有起点,那么这个起点就是GC Root。
也就是需要通过GC Root 找出所有活的对象,那么剩下所有的没有标记的对象就是需要回收的对象。
GC Root 的特点
- 当前时刻存活的对象!
哪些对象可以作为 GC Roots 的对象:
- 虚拟机栈中局部变量(也叫局部变量表)中引用的对象;
- 方法区中类的静态变量、常量引用的对象;
- 本地方法栈中 JNI (Native方法)引用的对象 ;
堆清理的方法
-
标记-清理, 缺点:内存碎片;
-
标记-整理,缺点: 代价大;
-
复制,缺点:2倍内存
实际堆区:
new
一个对象的时候都是现在Eden
区出生,当Eden
区快满的时候触发GC
(Young GC
),采用复制算法,复制到Survivor
区;Eden
区和两个Survivor
区容量比为,8:1:1
;- 两个
Survivor
区交替使用; - 每次复制算法其对像年龄+1,知道年龄到6岁就直接到Old区(>=6);
- Old区存储年龄>=6的对象,还直接存储大对象(在
Eden
区复制时消耗较大,比如一千万的int
数组); - Old区GC的时候同常伴随
Young GC
,所以叫FullGC
,此时会引起Stop the world
整个JAVA程序暂停全力进行垃圾回收采用标记清理和标记整理方法;
常用垃圾器
-
ParNew
收集器——年轻代,复制算法; -
CMS(Concurrent Mark Sweep)
收集器——老年代,标记清理算法; -
G1
全新;