怎么判断对象是否需要回收?
- 引用计数法:给对象添加一个
引用
计数器,每有一个地方引用
它就+1,引用
失效就-1,如果是0则回收。
- 优点:效率高;缺点:无法回收循环
引用
的对象- 可达性分析法:当一个对象到GC Roots对象没有任何
引用
链,则回收
- GC Roots对象包括虚拟机栈帧中
引用
的对象、方法区静态变量/常量引用
的对象、Native方法引用
的对象
那么如何判断对象是否被引用呢?
- 强引用:类似
Object obj = new Object()
,只要强引用存在,就不会回收掉- 软引用:用SoftReference来实现,用来描述还有用但非必需的对象,会在内存溢出之前回收
- 弱引用:用WeakReference来实现,用来描述非必需的对象,不管内存够不够在下一次垃圾回收时一定会被回收
- 虚引用:用PhantomReference来实现,虚引用的对象无法获得实例,随时都可能回收
垃圾回收算法?
- 标记-清除法:标记所有要回收的对象,然后回收
- 缺点:效率不高且会产生大量不连续的内存碎片,导致分配大对象时频繁GC
- 复制算法:一般用于新生代,将内存分成两块,每次只使用一块,每次回收都复制到另一块上,清除原来的空间
- 缺点:内存缩小一半,浪费
- 标记整理法:一般用于老年代,和标记清除法一样,但是在标记后先整理,然后再回收
如何真正实现垃圾回收?
具体介绍一下CMS?
- CMS基于标记-清除法,目标为获取最短回收停顿时间的收集器
- 共分为四个步骤:
- 初始标记:只标记一下GC Roots能连接的对象
- 并发标记:GC Roots tracing,即可达性分析
- 重新标记:修正并发标记期间因用户线程导致产生变动的对象的标记
- 并发清理:并发垃圾回收
- CMS优点:不停顿,并发执行。
- 缺点:并发执行对CPU资源压力大,且无法处理在处理过程中产生的垃圾,且标记清除法会产生垃圾碎片
具体介绍一下G1?
- G1是当前垃圾收集器最前沿成果之一,采用标记整理法,且能精确控制停顿时间
- 和CMS很类似,但是G1会把内存分成多个独立的区域,并根据允许回收的时间优先回收垃圾最多的区域
具体说一下新生代和老年代的对象
- 首先大多数情况,对象在新生代Eden区中分配。当Eden区空间不够时,会触发一次Minor GC(新生代GC)
- 大对象直接进入到老年代
- 长期存活的对象直接进入老年代。
- 对象在Eden区出生并经过一次Minor GC仍然存活且能被Survivor区容纳,会被移动到Survivor区,并且设置年龄为1岁。每熬过一次Minor GC年龄就+1
- 如果Survivor区中相同年龄的所有对象大小总和大于Survivor区的一半,那么年龄大于等于该年龄的对象都去老年代