MST

星途 面试题库

面试题:Java对象存活时间分析与垃圾回收机制关联

阐述Java垃圾回收机制是如何判断对象是否可以被回收的,结合对象存活时间分析,如果一个对象存在间接引用链,垃圾回收器会如何处理?在什么情况下,即使对象仍然可达,但也会被垃圾回收器回收?
10.7万 热度难度
编程语言Java

知识考点

AI 面试

面试题答案

一键面试

判断对象是否可被回收的方式

  1. 引用计数法:给对象添加一个引用计数器,每当有一个地方引用它时,计数器值就加1;当引用失效时,计数器值就减1。当计数器值为0时,就意味着该对象没有任何地方被引用,可以被回收。然而,Java并没有采用这种方式,因为它无法解决对象之间相互循环引用导致的内存泄漏问题。例如,对象A引用对象B,对象B引用对象A,若这两个对象之外没有其他引用指向它们,按引用计数法它们的引用计数都不为0,但实际上它们已无法被外部访问,却不会被回收。
  2. 可达性分析算法:Java使用该算法来判断对象是否可被回收。通过一系列称为 “GC Roots” 的根对象作为起始节点集,从这些节点开始,根据引用关系向下搜索,搜索过程所走过的路径称为引用链。如果一个对象到GC Roots间没有任何引用链相连,即从GC Roots到这个对象不可达时,则证明此对象是不可用的,可以被回收。GC Roots一般包含以下几种对象:
    • 虚拟机栈(栈帧中的本地变量表)中引用的对象,比如各个线程被调用的方法中使用到的参数、局部变量等。
    • 方法区中类静态属性引用的对象,例如Java类的引用类型静态变量。
    • 方法区中常量引用的对象,比如字符串常量池里的引用。
    • 本地方法栈中JNI(即一般说的Native方法)引用的对象

结合对象存活时间分析

对象的存活时间与它到GC Roots的可达性密切相关。当一个对象刚刚被创建且有引用指向它时,它是可达的,处于存活状态。随着程序的运行,如果指向该对象的引用逐渐被释放,直到没有任何引用链连接到GC Roots,那么该对象就进入了可回收状态。在可达性分析算法中,对象的存活时间就是从创建到与GC Roots断开连接的这段时间。

间接引用链的处理

如果一个对象存在间接引用链,只要这条间接引用链最终能连接到GC Roots,那么这个对象就是可达的,垃圾回收器不会回收它。例如,对象A引用对象B,对象B引用对象C,若对象A是GC Roots的直接或间接引用,那么对象C虽然是通过间接引用链连接到GC Roots,但依然是可达的,不会被回收。只有当从GC Roots出发,无论通过直接还是间接引用链都无法到达该对象时,它才会被判定为可回收对象。

即使对象仍然可达但被回收的情况

  1. 对象处于软引用状态且内存不足:当使用软引用(SoftReference)来引用对象时,在内存足够的情况下,这个对象不会被回收,因为它仍然可达。但当系统内存不足时,垃圾回收器会回收这些软引用指向的对象,以获取更多内存。例如,在缓存系统中使用软引用缓存图片等资源,当内存紧张时,这些缓存的图片就可能被回收。
  2. 对象处于弱引用状态:弱引用(WeakReference)的对象拥有更短暂的生命周期。无论内存是否充足,只要垃圾回收器开始工作,一旦发现弱引用对象,不管当前系统内存空间是否足够,都会回收它的内存。比如在一些场景中,希望某个对象在没有强引用指向它时,能被尽快回收,就可以使用弱引用。