垃圾回收
Garbage Collection,简称 GC,译作垃圾回收。将内存中、不会再被使用的对象视作“垃圾”,进而“回收”。
回收算法
引用计数
对象引用一次,引用计数器就加 1,失效时则减 1。
问题:
- 无法处理循环引用;
- 对象引用伴随加减法操作,影响性能;
标记清除
两个阶段:
- GCRoot 根搜索,标记所有可达对象;
- 清除所有未标记对象;
问题:
- 产生空间碎片
GC 根节点:
1 Java 栈中引用的对象
2 本地方法栈中引用的对象 2 方法区静态属性引用的对象
3 方法区常量引用的对象
复制算法(新生代)
将内存空间复制为两块,每次只使用其中一块。GC 时,将标记的可达对象复制到未使用的内存块中,然后清除正在使用的内存块。
优点:
- 效率较高(存活对象少,垃圾对象多);
- 不存在空间碎片;
问题:
- 系统内存折半;
新生代改进了复制算法,分为了 1 个 eden 区和 2 个相同的 survivor 区。在 GC 时,会将 eden 和正在使用的 1 个 survivor 区存活的对象复制到另外一个 survivor 区,并清除当前 eden 和 survivor。
标记压缩(老年代)
三个阶段:
- GCRoot 根搜索,标记所有可达对象;
- 将所有的可达对象压缩到内存的一端;
- 清理边界外所有的空间;
优点:
- 节省内存空间;
- 避免空间碎片;
分区
将整个堆空间划分成连续的不同小分区,每个小分区独立使用,独立回收。
相同条件下,堆空间越大,GC 耗时越长,产生的停顿就越长。
引用级别
软引用、弱引用非常适合保存缓存数据,不会导致内存溢出。
强
new 创建的对象,不可回收,会造成 OOM;
软
堆空间不足时会被回收;
弱
GC 时回收;
虚
随时回收,get 获取不到,又称幽灵引用,必须和引用队列一起使用;
Stop The World
为了保证系统一致性,JVM 在 GC 时会终止所有应用线程的执行,产生停顿,称之为“Stop The World”。