引用计数法和可达性分析
垃圾回收, 就是将已经分配出去的, 但却不在使用的内存回收回来, 以便再次分配. 在 Java 虚拟机语境下, 垃圾指的是死亡的对象所占据的堆空间. 下面就总结一下如何如何辨别一个对象是否死亡.
引用计数法: 为每一个对象添加一个引用计数器, 用来统计指向该对象的引用个数. 如果某个对象的引用计数器为 0, 则说明该对象已经死亡, 便可以被回收了.
通过引用计数法来标记对象的死亡和存活的过程中, 我们需要截获所有引用更新操作, 并且相应的增减目标对象的引用计数器. 这种方式除了需要额外的空间来存储计数器, 以及繁琐的更新操作, 引用计数法还有一个重大的漏洞: 无法处理循环引用对象. 比如: 对象 A,B 互相引用, 但是除此之外没有其他引用指向 A 或者 B. 这种情况下 A,B 其实已经死亡, 但是因为存在引用, 所以不会被垃圾回收, 造成内存泄露.
可达性分析: 将一系列 GC Roots 作为初始存活对象集合, 然后从该集合出发, 探索所有能够被该集合引用的对象, 并将其加入到该集合中, 这个过程就是标记. 标记的对象就是存活对象, 未标记到的就是死亡的对象.
什么是 GC Roots 呢? 可以暂时理解为由堆外指向堆内的引用, 常见的有以下几种:
1:Java 方法栈帧中的局部变量
2: 已加载的类的静态变量
3:JNI handles
4: 已启动且未停止的 Java 线程
可达性分析解决了引用计数法无法检测循环引用的问题, 但是本身也有自己的问题需要解决. 比如在多线程环境下, 其他线程可能会更新已经访问过的对象中的引用, 从而造成误报 (将引用设置为 null) 或者漏报(将引用设置为未被访问过的对象).
误报: 导致新产生的垃圾对象未被回收.
漏报: 导致原程序访问已经被回收的对象, 可能导致 Java 虚拟机直接崩溃.
Stop-the-world 以及安全点
为了解决上述问题, 在 Java 虚拟机里, 采用 Stop-the-world 方式, 停止其他非垃圾回收线程的工作, 直到完成垃圾回收. 这也造就了垃圾回收所谓的暂停时间 GC pause.
Java 虚拟机中的 Stop-the-world 是通过安全点 (safepoint) 机制来实现的. 当 Java 虚拟机收到 Stop-the-world 请求时, 它便会等待所有的线程到达安全点, 才允许请求 Stop-the-world 的线程进行独占的工作.
安全点的作用不是让线程停下, 而是找到让线程找到一个稳定的执行状态. 在这个状态下, Java 虚拟机的堆栈不会发生变化. 这样, 垃圾回收期便能够安全地执行可行性分析.
垃圾回收的三种方式
第一种: 清除.
把死亡对象所占据的内存标记为空闲内存, 并记录在一个空闲列表中. 当需要创建对象时, 内存管理块便会从该空闲列表中寻找空闲内存, 并划分给新建对象.
这种方式简单明了, 但是却有两个缺点. 第一: 造成内存碎片. 由于 Java 虚拟机的堆中对象必须是连续分布的, 因此可能出现总空闲内存足够, 但是无法分配的极端情况. 第二: 分配效率低. 如果是连续的内存空间, 可以通过指针加法来做分配. 而对于这种空闲列表, Java 虚拟机则需要住个访问列表中的项, 来查找能够存放入新建对象的空闲内存.
第二种: 压缩.
把存活的对象聚集到内存区域的起始位置, 从而留下一段连续的内存空间. 这种做法解决了内存碎片化的问题, 但是代价却是压缩算法的性能开销.
第三种: 复制.
内存区域分为两等分, 分别用两个指针 from 和 to 来维护, 并且只是用 from 指针指向的内存区域来分配内存. 当发生垃圾回收时, 把存活的对象复制到 to 指针指向的内存区域, 并且交换 from 指针和 to 指针的内容. 这种方法同样解决了内存碎片化的问题, 但是堆空间的使用效率及其地下, 只用到了一半.
问答
Q: 可达性分析 a 与 b 互为引用, 这不是死循环了吗, 为什么能被回收的
因为可达性分析只标记可达的, 如果 a 和 b 都不可达, 那么可达性分析标记不到, 就当成垃圾回收了.
Q: 对于为什么需要 stw 机制的解释还是有的困惑. 假如一个对象已经被标记为垃圾了, 其它线程怎么还会有机会引用它呢? 就算通过 stw, 把它标记并回收了, 那想引用它的线程重新恢复执行了会发生什么?
GC 标记的是活着的 (能够被引用到的) 对象, 剩下的是垃圾. 如果没有 STW, 其他线程在垃圾回收过程中产生了垃圾(某对象不再被引用), 那么会被漏掉.
总结
本文创作灵感来源于 极客时间 郑雨迪老师的《深入拆解 Java 虚拟机》课程, 通过课后反思以及借鉴各位学友的发言总结, 现整理出自己的知识架构, 以便日后温故知新, 查漏补缺.
来源: https://www.cnblogs.com/yuepenglei/p/10309046.html