Bohr-L Bohr-L
首页
技术
常见面试题
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

刘博

I'm a slow walker, But I never walk backwards.
首页
技术
常见面试题
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • 数据处理与存储类

  • Spring 生态类

  • 缓存问题类

  • 多线程类

  • JVM 类

    • JVM 中一次完整的 GC 流程(从 ygc 到 fgc)是怎样的
    • 如何判断对象可以被回收
      • 你知道哪些垃圾收集算法
      • 虚拟机为什么使用元空间替换了永久代
      • 简述 CMS 垃圾收集器的工作流程,它有什么优缺点?
      • 简述一下 JVM 的内存模型
      • 说说堆和栈的区别
      • 简述 Java 的对象结构
      • JVM 中的即时编译器(JIT)如何工作?
      • 什么是内存屏障?JVM 如何使用内存屏障保证指令执行顺序?
      • 如何排查和解决 JVM 内存泄漏问题?有哪些常用的工具和方法?
      • JVM 如何处理异常?try-catch-finally 结构在字节码层面是如何实现的?
    • MySQL 类

    • Java 8 + 特性类

    • 其他技术类

    • 常见面试题
    • JVM 类
    刘博
    2025-12-28
    目录

    如何判断对象可以被回收

    JVM 判断对象是否可回收的核心是 “对象是否再被引用”,主要通过 “可达性分析算法” 实现,同时结合 “引用类型” 和 “finalize () 方法” 辅助判断,具体流程如下:

    # 1. 核心算法:可达性分析(Reachability Analysis)

    • 原理:从 “GC Roots”(一组活跃的引用)出发,遍历对象的引用链;若一个对象无法通过任何 GC Roots 到达(即引用链断裂),则该对象被标记为 “不可达”,视为可回收对象。
    • GC Roots 的类型:
      • 线程栈中正在执行的方法的局部变量表引用的对象(如方法参数、局部变量);
      • 方法区中静态变量引用的对象(如static Object obj = new Object());
      • 方法区中常量引用的对象(如final Object obj = new Object());
      • 本地方法栈中 JNI(Java Native Interface)引用的对象(如调用 C++ 方法时的引用);
      • 活跃线程对象(如正在运行的 Thread 对象);
      • 被同步锁(synchronized)持有的对象。

    # 2. 引用类型:影响对象回收时机

    Java 中的引用分为 4 种类型(从强到弱),不同引用类型的对象,回收时机不同:

    • 1. 强引用(Strong Reference):
      • 最常见的引用(如Object obj = new Object()),只要强引用存在,对象就不会被回收;
      • 即使内存不足,JVM 也会抛出OutOfMemoryError,不会回收强引用对象。
    • 2. 软引用(Soft Reference):
      • 通过SoftReference类实现(如SoftReference<Object> softRef = new SoftReference<>(new Object()));
      • 当内存充足时,对象不被回收;当内存不足(即将发生 OOM)时,JVM 会回收软引用对象;
      • 应用场景:内存敏感的缓存(如图片缓存,内存不足时自动清理)。
    • 3. 弱引用(Weak Reference):
      • 通过WeakReference类实现(如WeakReference<Object> weakRef = new WeakReference<>(new Object()));
      • 无论内存是否充足,只要发生 GC(YGC 或 FGC),弱引用对象都会被回收;
      • 应用场景:临时缓存(如 ThreadLocal 中的 value,避免内存泄漏)。
    • 4. 虚引用(Phantom Reference):
      • 通过PhantomReference类实现,必须与ReferenceQueue配合使用;
      • 虚引用不影响对象的回收,仅在对象被回收时,将虚引用加入ReferenceQueue,用于跟踪对象的回收状态;
      • 应用场景:管理直接内存(如 NIO 的 DirectBuffer,回收时释放直接内存)。

    # 3. 辅助判断:finalize () 方法的 “救赎”

    • 原理:每个对象都有finalize()方法(定义在Object类中),当对象被可达性分析标记为不可达后,JVM 会先将对象放入 “F-Queue” 队列,由低优先级的 “Finalizer 线程” 执行对象的finalize()方法;
    • “救赎” 机会:在finalize()方法中,若对象重新建立与 GC Roots 的引用(如obj = this),则对象会被移出 “待回收” 状态,避免被回收;
    • 注意事项:
      • finalize()方法仅执行一次,若对象再次被标记为不可达,不会再执行finalize();
      • finalize()方法执行时间不确定(可能被阻塞),且效率低,不推荐使用,推荐用try-finally或AutoCloseable管理资源。

    # 4. 特殊情况:对象的 “自我救赎” 失效

    • 若对象的finalize()方法未重写,或已执行过一次,即使在finalize()中重新建立引用,也无法避免被回收;
    • 若 “Finalizer 线程” 执行finalize()方法时抛出异常,异常会被忽略,对象仍会被回收。

    # 总结

    JVM 判断对象可回收的流程:

    1. 通过可达性分析,标记不可达对象;
    2. 根据引用类型,确定对象的回收优先级(强引用 > 软引用 > 弱引用 > 虚引用);
    3. 若对象是不可达且无强引用,执行finalize()方法,给予 “救赎” 机会;
    4. 若 “救赎” 失败,对象被确定为 “可回收”,等待 GC 时被清理。

    上次更新: 12/30/2025
    JVM 中一次完整的 GC 流程(从 ygc 到 fgc)是怎样的
    你知道哪些垃圾收集算法

    ← JVM 中一次完整的 GC 流程(从 ygc 到 fgc)是怎样的 你知道哪些垃圾收集算法→

    最近更新
    01
    CPU 使用率较高排查和解决
    12-29
    02
    JVM OOM 问题如何排查和解决
    12-29
    03
    接口防刷怎么实现?
    12-29
    更多文章>
    Theme by Vdoing | Copyright © 2025-2026 Bohr-L's note
    • 跟随系统
    • 浅色模式
    • 深色模式
    • 阅读模式