关于Java中引用的面试题

2023-10-18 16:27:25 浏览数 (2)

关于Java中引用的面试题

一、介绍

在Java中,有以下四种类型的引用:强软弱虚

  1. 强引用(Strong Reference):最常见的引用类型,也是默认的引用类型。如果一个对象具有强引用,那么垃圾回收器就不会回收这个对象。
  2. 软引用(Soft Reference):如果一个对象具有软引用,那么当系统内存不足时,垃圾回收器会尝试回收该对象。软引用通常用于缓存中,以便在内存紧张时释放一些缓存。
  3. 弱引用(Weak Reference):如果一个对象具有弱引用,那么它的生命周期更短,它在任何时候都可能被垃圾回收器回收。弱引用通常用于外部引用内部对象时使用,以免内存泄漏。
  4. 虚引用(Phantom Reference):虚引用是所有引用类型中最弱的一种。如果一个对象具有虚引用,那么它就像没有被引用一样,随时会被垃圾回收器回收。虚引用主要用于跟踪对象被回收的状态。

上面属于Java的面试八股文,那么在面试之中,我们该如何进行理解输出呢?

二、引用

1)强引用(Strong Reference)

在日常开发中最为平常的引用,因为我们直接new出来的对象就属于强引用。

那么,如果一个对象只要有强引用,那么GC就不会回收掉它。如下这个类

代码语言:javascript复制
package com.banmoon.reference;

public class Reference {

    @Override
    protected void finalize() throws Throwable {
        System.out.println("GC回收");
        super.finalize();
    }
}

我只有将引用设置为null后,GC才能回收掉它,强引用就是如此。

代码语言:javascript复制
package com.banmoon.reference;

import java.io.IOException;

public class StrongReference {

    public static void main(String[] args) throws IOException {
        Reference reference = new Reference();
        System.out.println(reference);
        // 赋值为null,取消对象的强引用
        reference = null;
        // 通知进行gc
        System.gc();
        System.out.println(reference);
        // 阻塞一下
        System.in.read();
    }

}

2)软引用(Soft Reference)

软引用和强引用不同

  • 强引用只要有引用指向对象,对象就不会被回收
  • 而软引用,就算有软引用指向对象,在发生内存不足的时候,GC就会把这些软引用的对象给回收

为了测试下面的代码,我们需要添加一点JVM参数,限制一下JVM的内存,即-Xms20M -Xmx20M,我限制了20M的内存

代码语言:javascript复制
package com.banmoon.reference;

import java.lang.ref.SoftReference;
import java.util.concurrent.TimeUnit;

public class SoftReferenceMain {

    public static void main(String[] args) throws InterruptedException {
        // 一个byte数组,内容大小是10M
        SoftReference<byte[]> sr = new SoftReference<>(new byte[1024 * 1024 * 10]);
        // 获取数组
        System.out.println(sr.get());
        // 睡眠一秒后,再次查看数组
        TimeUnit.SECONDS.sleep(1);
        System.out.println(sr.get());

        // 我再创建一个数组,12M,再次查看原来软引用的数组
        byte[] bytes = new byte[1024 * 1024 * 12];
        System.out.println(sr.get());
    }
    
}

3)弱引用(Weak Reference)

比起上面的两个引用,弱引用可以这样理解,它引用的对象,只要发生GC,就都会被回收。

也就是说,前两个引用都一定程度上保护了对象,但弱引用不行,弱引用保护不了任何对象。

在平常的使用中,基本没啥用,当然ThreadLocal中使用到了,搭配着强引用一起进行使用的。

简单改造一下强引用的代码,变成弱引用,GC后会发生什么

代码语言:javascript复制
package com.banmoon.reference;

import java.io.IOException;
import java.lang.ref.WeakReference;
import java.util.concurrent.TimeUnit;

public class WeakReferenceMain {

    public static void main(String[] args) throws IOException, InterruptedException {
        WeakReference<Reference> wr = new WeakReference<>(new Reference());
        System.out.println(wr.get());
        // 通知进行gc,并阻塞一下
        System.gc();
        TimeUnit.SECONDS.sleep(1);
        // 查看输出
        System.out.println(wr.get());
    }

}

4)虚引用(Phantom Reference)

最后一个虚引用,比较特殊。主要是给GC使用的,对的没错,JVMGC的时候,也会创建对象,这些基本就是虚引用。

下面作为示例了解一下

代码语言:javascript复制
package com.banmoon.reference;

import java.lang.ref.PhantomReference;
import java.lang.ref.ReferenceQueue;

public class PhantomReferenceMain {

    public static void main(String[] args) throws InterruptedException {
        ReferenceQueue<Reference> queue = new ReferenceQueue<>();
        PhantomReference<Reference> phantom = new PhantomReference<>(new Reference(), queue);

        //检查垃圾回收队列中是否已经加入该对象
        System.out.println("Is queued: "   phantom.isEnqueued());

        //强制进行垃圾回收并等待GC完成
        System.gc();
        Thread.sleep(1000);

        //检查垃圾回收队列中是否已经加入该对象
        System.out.println("Is queued: "   phantom.isEnqueued());

        //从队列中读取并打印垃圾回收的信息
        System.out.println(queue.poll());
    }

}

虚引用的使用场景 虚引用通常用于实现比弱引用更加精细的对象 finalization(终结)处理逻辑。虚引用通常与引用队列结合使用,对于一个具有虚引用的对象,当垃圾回收器准备回收该对象时,如果发现它存在虚引用,就会在回收对象的内存之前,将这个虚引用加入到与之关联的引用队列中。 在实际应用中,虚引用常用于:

  1. 用于在对象被回收时进行一些定制操作,例如发送通知、记录日志、清理资源等等。
  2. 用于避免内存泄漏,通过使用虚引用表示该对象将会被垃圾回收器回收,并触发一些清理操作。

值得注意的是,虚引用并不会影响被引用对象的生命周期。当垃圾回收器准备回收对象时,虚引用会被加入到与之关联的引用队列中,但此时虚引用本身并不能保证被回收,需要不断调用getReference()方法来获取引用队列中的虚引用,直到返回null为止。

三、最后

关于GC回收强引用的对象,有时候就算被强引用,也还是会被回收的场景,比如说循环引用。所以还是得具体情况,具体分析。

我是半月,你我一同共勉!!!

0 人点赞