• java的4种引用类型


    原创文章:java的4种引用类型 – 编程屋

    目录

    1 前言

    2  4种引用类型

    2.1 强引用

    2.2 软引用

    2.3 虚引用

    2.4 弱引用


    1 前言

    java中的4种引用类型,强引用软引用弱引用虚引用。说这4种引用之前,需要先说一下垃圾回收机制中的finalize()方法,

    finalize()方法是Object中的方法,它只有一个空的方法体,并且被protected修饰:

     当一个java对象被当成垃圾回收的时候,垃圾回收器会负责调用finalize()方法。

    2  4种引用类型

    2.1 强引用

    强引用:一般来讲就是直接被new出来的对象(Object o = new Object();),只要强引用存在,垃圾回收器就不会回收被引用的对象。

    为了证明上述结论,可以做以下验证。

    1)重写finalize()方法,因为Object中的finalize()方法只有一个空的方法体,不方便进行测试。

    1. public class Person {
    2. @Override
    3. protected void finalize() throws Throwable {
    4. super.finalize();
    5. System.out.println("finalize");
    6. }
    7. }

    2)测试方法进行测试

    1. public static void main(String[] args) throws IOException {
    2. Person person = new Person();
    3. System.gc();//触发垃圾回收
    4. System.out.println(person);
    5. System.in.read();//阻塞main线程,给垃圾回收线程执行
    6. }

    解析:创建一个Person对象,此时是一个强引用,即便是触发了垃圾回收,垃圾回收器也不会回收被引用的对象。

    结果输出了person对象地址,并没有输出finalize()方法体中语句。

     那如果将该强引用删掉呢(将person置为null就行)

    1. public static void main(String[] args) throws IOException {
    2. Person person = new Person();
    3. person = null;
    4. System.gc();//触发垃圾回收
    5. System.out.println("person:"+person);
    6. System.in.read();//阻塞main线程,给垃圾回收线程执行
    7. }

    再次执行,发现该对象被回收掉。

    2.2 软引用

    软引用:如果一个对象只具有软引用,并且当前虚拟机的内存足够,那么它就不会被垃圾回收器回收,否则就会回收软引用对象。

    1. public static void main(String[] args) {
    2. SoftReference<byte[]> softReference = new SoftReference<>(new byte[1024 * 1024 * 10]);
    3. System.out.println("softReference:"+softReference.get());
    4. System.gc();
    5. try { //进行睡眠让垃圾回收有时间执行
    6. Thread.sleep(500);
    7. } catch (InterruptedException e) {
    8. e.printStackTrace();
    9. }
    10. System.out.println("softReference:"+softReference.get());
    11. }

    分析下以上代码:

    SoftReference softReference = new SoftReference<>(new byte[1024 * 1024 * 10]);

     创建了一个10m大小的byte对象,放到了软引用对象中,并且有一个softReference对象指向了软引用对象。如下:

     为了证明上述所说情况在内存足够的情况下运行。控制台输出如下:

     可以发现软引用对象并没有被垃圾回收。但是如果将虚拟机内存最大设置为20M,并且再创建一个10M的字节数组,它还会这样不会被回收吗?

     再次创建一个字节数组。

    1. public static void main(String[] args) {
    2. SoftReference<byte[]> softReference = new SoftReference<>(new byte[1024 * 1024 * 10]);
    3. System.out.println("softReference:"+softReference.get());
    4. System.gc();
    5. try { //进行睡眠让垃圾回收有时间执行
    6. Thread.sleep(500);
    7. } catch (InterruptedException e) {
    8. e.printStackTrace();
    9. }
    10. System.out.println("softReference:"+softReference.get());
    11. byte[] bytes = new byte[1024 * 1024 * 10];
    12. System.out.println("softReference:"+softReference.get());
    13. }

    控制台输出:

    可以发现此时,软引用对象已经被回收。

    由此可以证明如果一个对象只具有软引用,并且当前虚拟机的内存足够,那么它就不会被垃圾回收器回收,否则就会回收软引用对象。

    通常软引用用作缓存处理,先从软引用中获取,如果没有获取到,再从缓存中获取。

    2.3 虚引用

    虚引用:虚引用必须与引用队列(ReferenceQueue)一起使用,当垃圾回收器准备回收一个对象时,如果发现它有虚引用,就会把这个虚引用加入到与之相关联的队列中,然后就可以通过监听引用队列得知虚引用的回收。

    1. private static final List<Object> LIST = new LinkedList<>();
    2. private static final ReferenceQueue<Person> QUEUE = new ReferenceQueue<>();
    3. public static void main(String[] args) {
    4. PhantomReference<Person> phantomReference = new PhantomReference<>(new Person(), QUEUE);
    5. System.out.println(phantomReference.get()); //null
    6. //设置-Xmx20M,向内存中放置大小
    7. new Thread(()->{
    8. while (true){
    9. LIST.add(new byte[1024 * 1024]);
    10. try {
    11. Thread.sleep(500);
    12. } catch (InterruptedException e) {
    13. e.printStackTrace();
    14. }
    15. System.out.println(phantomReference.get());
    16. }
    17. }).start();
    18. new Thread(()->{
    19. while (true) {
    20. Reference<? extends Person> poll = QUEUE.poll();
    21. if (poll != null ) {
    22. System.out.println("虚引用对象被jvm回收了======="+poll);
    23. }
    24. }
    25. }).start();
    26. try {
    27. Thread.sleep(500);
    28. } catch (InterruptedException e) {
    29. e.printStackTrace();
    30. }
    31. }
    1. public class Person {
    2. @Override
    3. protected void finalize() throws Throwable {
    4. super.finalize();
    5. System.out.println("finalize");
    6. }
    7. }

     代码解析:

    1)全局定义一个LIST集合和一个引用队列QUEUE

    2)定义一个虚引用对象phantomReference并将测试回收对象Person以及队列放入其中。

    3)将虚拟机大小设置最大为20M

    4)设置两个线程,一个线程向内存中不断的添加大小(目的是内存满了之后垃圾回收机制回收Person类并将虚引用放入引用队列QUEUE中)另外一个线程是为了测试是否拿到放入队列中的线程。

    控制台输出如下:

     发现结论是正确的。

    2.4 弱引用

    以上只是部分内容,为了维护方便,本文已迁移到新地址:java的4种引用类型 – 编程屋

  • 相关阅读:
    干货!手把手教你穿透内网
    期货交易需要多大的本钱?仓位怎么分配?
    yjs demo: 多人在线协作画板
    Linux -- 进阶 Web服务器 搭建基于 https 协议的静态网站 ( 预备知识 )
    如何在Mac上停止旋转等待光标?这里提供详细步骤
    【AWS实验】 配置中转网关及对等连接
    PMP每日一练 | 考试不迷路-11.24(包含敏捷+多选)
    汽车网络安全--ECU的安全更新
    java:内部类
    Android修行手册 - TabLayout全解析 - 和ViewPager联动
  • 原文地址:https://blog.csdn.net/qq_50652600/article/details/127095167