强、软、弱、虚,你是哪一种?

简介: 强、软、弱、虚,你是哪一种?

前言

了不起最近在整理一些面试资料,发现对于强、软、弱、虚引用的资料少之又少,所以决定整理一下关于这方面的资料,方便金三银四跳槽。

强引用

特点

强引用是较为普遍的一种引用,在我们编写Java代码时,绝大多数的引用,使用的都是强引用。当一个对象使用的是强引用时,JVM垃圾回收器不会回收该对象,即使内存不足,JVM宁愿抛出OOM异常,也不会主动去回收该对象。

代码示例

public class StrongReference {
    public static void main(String[] args) {
        MyObject myObject = new MyObject();
        System.gc();
        System.out.println("第一次gc,myObject = " + myObject);
        // 手动置为Null,并通知JVM进行垃圾回收
        myObject = null;
        System.gc();
        System.out.println("第二次gc,myObject = " + myObject);
    }
}
class MyObject{
    @Override
    protected void finalize() throws Throwable {
        System.out.println("execute finalize method...");
    }
}
// 执行结果:
// 第一次gc,myObject = ref.MyObject@1b6d3586
// 第二次gc,myObject = null
// execute finalize method...

软引用

特点

软引用是一种较强的引用类型,当内存足够时,JVM不会回收软引用的对象,当内存不足时,JVM会回收软引用的对象。

代码示例

前置条件:调整JVM参数,将最大内存调整为10MB。-Xms10m -Xmx10m
import java.lang.ref.SoftReference;
import java.util.concurrent.TimeUnit;
public class SoftReferenceExample {
    public static void main(String[] args) {
        SoftReference softReference = new SoftReference<MyObject>(new MyObject());
        System.out.println("gc before, softReference = " + softReference.get());
        System.gc();
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("gc after, softReference = " + softReference.get());
        try {
            // 创建20MB的字节数组
            byte[] bytes = new byte[20 * 1024 * 1024];
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            System.out.println("memory not enough, softReference = " + softReference.get());
        }
    }
}
// 执行结果:
// gc before, softReference = ref.MyObject@1b6d3586
// gc after, softReference = ref.MyObject@1b6d3586
// Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
//   at ref.SoftReferenceExample.main(SoftReferenceExample.java:22)
// memory not enough, softReference = null
// execute finalize method...

弱引用

特点

弱引用是一种比软引用更弱的引用类型,无论内存是否充足,JVM垃圾回收器都会立即回收弱引用对象。

代码示例

import java.lang.ref.WeakReference;
import java.util.concurrent.TimeUnit;
public class WeakReferenceExample {
    public static void main(String[] args) {
        WeakReference weakReference = new WeakReference<>(new MyObject());
        System.out.println("gc before, softReference = " + weakReference.get());
        System.gc();
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("gc after, softReference = " + weakReference.get());
    }
}
// 执行结果:
// gc before, softReference = ref.MyObject@1b6d3586
// execute finalize method...
// gc after, softReference = null

虚引用

特点

虚引用是最弱的引用类型,主要用于跟踪对象是否被垃圾回收器回收。同时,虚引用必须与一个引用队列一同使用。当JVM准备回收一个对象时,如果发现它是虚引用,那么会将这个虚引用加入到与之关联的一个引用队列中。

代码示例

import java.lang.ref.PhantomReference;
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
public class PhamtonReferenceExample {
    public static void main(String[] args) throws InterruptedException {
        ReferenceQueue<MyObject> referenceQueue = new ReferenceQueue<>();
        PhantomReference<MyObject> phantomReference = new PhantomReference<>(new MyObject(), referenceQueue);
        List<byte[]> list = new ArrayList<>();
        new Thread(() -> {
            while (true) {
                list.add(new byte[2 * 1024 * 1024]);
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(phantomReference.get() + "\t" + "list add success!!!");
            }
        }).start();
        new Thread(() -> {
            while (true) {
                Reference<? extends MyObject> ref = referenceQueue.poll();
                if (ref != null) {
                    System.out.println("虚对象回收加入了对列");
                    break;
                }
            }
        }).start();
    }
}
// 执行结果:
// execute finalize method...
// null  list add success!!!
// null  list add success!!!
// null  list add success!!!
// Exception in thread "Thread-0" java.lang.OutOfMemoryError: Java heap space
//    at ref.PhamtonReferenceExample.lambda$main$0(PhamtonReferenceExample.java:21)
//   at ref.PhamtonReferenceExample$$Lambda$1/1324119927.run(Unknown Source)
//    at java.lang.Thread.run(Thread.java:748)
// 虚对象回收加入了对列

总结

引用类型可用于灵活管理对象的生命周期,且在Java源码中有较多的应用场景,如ThreadLocal使用的就是弱引用。希望本文能够帮助小伙伴们对Java的四种引用类型有更深入的了解。

相关文章
|
8月前
|
机器学习/深度学习 传感器 编解码
BSRGAN超分辨网络
BSRGAN超分辨网络
103 0
|
8月前
|
机器学习/深度学习 编解码
ESRGAN超分辨网络
ESRGAN超分辨网络
91 0
|
算法 调度
转:使用匈牙利算法对局域网共享软件有哪些好处
在局域网共享软件中,匈牙利算法主要应用于解决资源分配的问题。局域网共享软件可能存在多个用户同时访问同一文件或打印机的情况,为了确保资源的公平共享,需要对资源进行分配。
95 2
|
负载均衡 网络协议 网络虚拟化
变形金刚外传0x08-动态路由实现物理-逻辑互访
在上一篇分享中,我通过设置静态路由条目,实现了NSX-T演示环境中,逻辑网络与物理网络的三层互通。虽然静态路由没有动态路由协议的灵活性,但在一些情况下,静态路由却是首选的方案:
|
负载均衡 安全 测试技术
变形金刚外传0x11-T1SR承载负载平衡器用例
在之前连续几篇分享中,我向各位演示了如何利用分级逻辑路由器实现跨KVM和vSphere、跨逻辑与物理网络的三层互访。在谈及逻辑路由架构设计的时候,我建议将负载平衡器(后文称LB)、网络地址转换(NAT)等通过Tier1级别的逻辑路由器(后文称T1LR)实现。在这种架构设计下,Tier0级别的逻辑路由器(后文称T0LR)可以采用Active-Active架构来满足带宽利用率的最大化。并且,一般在分级架构中,Tier0级别扮演的更多是运营商级别的角色;Tier1级别扮演的更多是租户级别的角色;在T1LR级别实现包括LB在内的网络功能虚拟化(NFV),更能贴近通过运管平台纳管NSXDC实现网络与安全
《逻辑与计算机设计基础(原书第5版)》——2.7 门的传播延迟
本节书摘来自华章计算机《逻辑与计算机设计基础(原书第5版)》一书中的第2章,第2.7节,作者:(美)M.莫里斯·马诺(M. Morris Mano)著, 更多章节内容可以访问云栖社区“华章计算机”公众号查看。
3859 1
|
机器学习/深度学习 自然语言处理
注意力机制可分为软和硬两类,空间域,通道域
注意力机制是当前深度学习领域比较流行的一个概念。其模仿人的视觉注意力模式,每次只关注与当前任务最相关的源域信息,使得信息的索取更为高效。
741 0
注意力机制可分为软和硬两类,空间域,通道域
|
Java
强、软、弱、虚引用
强、软、弱、虚引用
97 0
|
存储 缓存 Java
Java对象引用四个级别(强、软、弱、虚)
最近,高级Java技术栈微信群中,有一些猿友在讨论JVM中对象的周期问题,有谈到引用的级别,现在为大家做个总结吧,虽然大多数公司并没有意识或者用到这些引用,但了解这些基本概念对熟悉整个垃圾回收机制和面试是非常有帮助的。
141 0
Java对象引用四个级别(强、软、弱、虚)
|
缓存 Java 程序员
Java 强、弱、软、虚,你属于哪一种?
Java中的四种引用 Java中有四种引用类型:强引用、软引用、弱引用、虚引用。