java=中=的=四=种=引=用

主要了解,强、软、弱、虚四种引用在垃圾回收时候的不同表现。垃圾回收的时候,会调用对象的 finalize() 方法。finalize() 这个方法我们一般需要去重写它,也不应该去重写它,调用它。

强引用

普通的引用就是强引用。只要强引用指向一个对象,GC就永远不会回收这个对象。

public class T01_NormalReference {
    public static void main(String[] args) throws IOException {
        M m = new M();
        m = null;//释放对象,再无指针指向对象
        // 显示调用GC
        System.gc(); //DisableExplicitGC
		// 阻塞住当前线程,GC是泡在别的线程里的,如果main线程直接走完退出了,那么整个程序就退出了,那么GC不GC也就没有什么意义了。
        System.in.read();// 无任何含义,只是为了阻塞住当前线程。
    }
}

软引用(SoftReference)

如果一个软引用指向一个对象,只有在内存不够用的情况下,GC才会回收这个对象。也就是说即使手动调用GC,只要内存够用,就不会回收。

  • 软引用非常适合缓存使用(面试说说,一般实际用Redis)
/**
 * 软引用
 * 软引用是用来描述一些还有用但并非必须的对象。
 * 对于软引用关联着的对象,在系统将要发生内存溢出异常之前,将会把这些对象列进回收范围进行第二次回收。
 * 如果这次回收还没有足够的内存,才会抛出内存溢出异常。
 * -Xmx20M
 */
public class T02_SoftReference {
    public static void main(String[] args) {
    	// 声明一个软引用指向一个1024*1024*10大小字节数组
        SoftReference<byte[]> m = new SoftReference<>(new byte[1024*1024*10]);
        //m = null;
        System.out.println(m.get());
        System.gc();
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(m.get());

        //再分配一个数组,heap将装不下,这时候系统会垃圾回收,先回收一次,如果不够,会把软引用干掉
        byte[] b = new byte[1024*1024*15];
        System.out.println(m.get());//get为空
    }
}

**弱引用(WeakReference)面试重点

弱引用遭到gc就会回收。它的作用是什么呢?(重点!)

作用

如果一个弱引用和有另外一个强引用指向同一个对象,只要这个强引用消失掉,我这个弱引用就不应该再管这个对象了。用在什么地方,一般用在容器里(记住这个结论)。一个典型的应用就是 ThreadLocal。

import java.lang.ref.WeakReference;

public class T03_WeakReference {
    public static void main(String[] args) {
        WeakReference<M> m = new WeakReference<>(new M());

        System.out.println(m.get());//有值
        System.gc();
        System.out.println(m.get());//空值

        ThreadLocal<M> tl = new ThreadLocal<>();
        tl.set(new M());
        tl.remove();
    }
}

作业

看一下WeakHashMap有什么作用。

  • 它是一个弱指针版本的HashMap,它里面维护了一个Entry的数组 table,Entry继承自弱引用WeakReference的的键值对。通过对 key 进行hash的方式得到其在 table 中的偏移量index,从而通过 table[index] 的方式,检索出 key 对应的 Entry 键值对。
    在这里插入图片描述

虚引用

虚引用就干一件事,管理堆外内存的。如果有面试官问你这个问题,还能把堆外内存给解释清楚,那可牛大了。虚引用,基本没用,不是给程序员用的,是给写JVM虚拟机的人用的。

创建虚引用 PhantomReference,需要传给他一个 ReferenceQueue队列QUEUE。一旦虚引用被回收,这个虚引用会被装到这个QUEUE里,然后让你接收到一个通知。什么时候你检测到一个QUEUE里头有一个虚引用存在了,那说明什么呢?说明这个虚引用被回收了。虚引用PhantomReference是一个特别虚的引用,垃圾回收的时候,二话不说上来就把它干掉,只要看见就给它干掉。

虚引用干这样一件事,当这个对象被干掉的时候,你会收到一个通知,通知你的方式是,往这个队列QUEUE里扔进一个值。 什么时候内存满了出发垃圾回收的时候,另外一个线程就不断地监测这个队列QUEUE里有没有值啊,有没有值啊?如果有的话就说迷你跟这个值被扔进去了。所以如果你想得到这个通知,你就不断的去检测,这个队列里面有没有值,如果有,就说明虚引用被回收了。

public class T04_PhantomReference {
    private static final List<Object> LIST = new LinkedList<>();
    private static final ReferenceQueue<M> QUEUE = new ReferenceQueue<>();

    public static void main(String[] args) {

        PhantomReference<M> phantomReference = new PhantomReference<>(new M(), QUEUE);

        new Thread(() -> {
            while (true) {
                LIST.add(new byte[1024 * 1024]);
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                    Thread.currentThread().interrupt();
                }
                System.out.println(phantomReference.get());
            }
        }).start();

        new Thread(() -> {
            while (true) {
                Reference<? extends M> poll = QUEUE.poll();
                if (poll != null) {
                    System.out.println("--- 虚引用对象被jvm回收了 ---- " + poll);
                }
            }
        }).start();

        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
  • 虚引用,你往里面get值,是get不到的。那它连一个值也拿不到,到底用来干嘛的?再说一遍,只是为了给你一个通知
  • 写JVM的人,拿它来怎么用呢?有这么一种情况。NIO里面有一个比较新的buffer叫DirectBuffer,这个缓存不被JVM管理,而是直接被操作系统控制,又叫做堆外内存,这个buffer是指向堆外内存的,如果这个buffer设为空,垃圾回收器会自动回收它所对应的堆外内存吗,不会回收,也没法回收。那么写JVM的人怎么回收它呢?当检测到虚引用被这个垃圾回收器回收的时候,代码手动去回收堆外内存,通过c/C++的delete或者free函数。
  • 现在Java里也提供了一个可以分配/手动回收堆外内存的方式,就是通过Unsafe。Unsafe这个类在JUC里头很多操作都用到了它,它里头有很多cas操作。
    在这里插入图片描述
发布了40 篇原创文章 · 获赞 0 · 访问量 409

猜你喜欢

转载自blog.csdn.net/weixin_43780400/article/details/105510126