Java的引用类型常用的四种方法
作者:? 发布时间:2023-11-29 14:05:24
前言
今天看代码看到有牵扯到弱引用的东西,就先稍微补一补Java的四种引用类型吧。Java为引用类型专门定义了一个类Reference
,它是引用对象的抽象基类。
这个类定义了所有引用对象共有的操作。 由于这个类和垃圾收集器是息息相关的,这个类不能直接子类化。
Reference有4个子类,分别为强引用FinalReference、软引用SoftReference、弱引用weakReference、虚引用PhantomReference。
意思就是这四种引用是在JVM中GC用的,我们工作写代码根本用不着。
强引用FinalReference
Object obj = new Object();
上面我们new了一个Object对象,并将其赋值给obj,这个obj就是new Object()的强引用。
Java中的引用默认就是强引用。
强引用的特性是只要有强引用存在,被引用的对象就不会被垃圾回收。只有强引用不存在了,被引用的对象才会被垃圾回收。
写个demo吧,新建一个BeanA,重写finalize方法:
public class BeanA {
@Override
protected void finalize(){
System.out.println("将对象从内存中清除出去");
}
}
然后写个测试方法,将强引用置为空后,通知JVM垃圾回收。
public static void main(String[] args) throws IOException {
BeanA a = new BeanA();
a=null;
System.gc();
//防止gc线程结束后还未执行finalize方法
System.in.read();
}
输出结果:将对象从内存中清除出去。
可以看到强引用不存在了,被引用的对象是可以被垃圾回收的。
软引用SoftReference
软引用是用于描述一些有用但非必需的引用。
SoftReference的实例保存一个Java对象的软引用,该软引用的存在不影响垃圾回收线程对该Java对象的回收。
意思就是只有在内存不足的情况下,被引用的对象才会被回收,内存够用是不会被回收的。
只要垃圾回收器没有回收它,该对象就可以被程序使用。和这个软引用是没有关系的(即没有将软引用置空),只和内存有关。
直接看demo:
public static void main(String[] args){
SoftReference<byte[]> soft = new SoftReference<>(new byte[1024*1024*10]);
System.out.println(soft.get());
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.gc();
//注释掉下面这句两次get()方法都能获取到
//byte[] bytes = new byte[1024 * 1024 * 15];
System.out.println(soft.get());
}
我们创建了一个SoftReference对象,其变量名soft强引用着这个SoftReference对象,而这个SoftReference对象则保存着一个软引用,这个软引用引用的是一个10M的数组。
当然这个10M数组也可以替换成自己新建的对象:
A a=new A();
SoftReference<A> soft =new SoftReference<>(a);
这样的话SoftReference对象中保存的a就变成了软引用,如果内存足够的话,将a=null,GC后使用soft.get还是可以获取到该对象。
我们这里使用10M数组来测试,启动测试类设定VM内存20M,发现再新建一个15M数组后会将原来的10M数组给GC掉。
输出结果:
[B@2cfb4a64
[B@2cfb4a64[B@2cfb4a64
null
总结一句话就是:创建强引用时内存不够就把软引用占的内存给回收掉。
总结一个词就是:欺软怕硬。
另外软引用非常适合缓存使用。
弱引用weakReference
弱引用和软引用很类似,不同的是弱引用引用的对象只要垃圾回收执行,就会被回收,而不管是否内存不足。
我demo没有设定vm:Xmx=20M,通知JVM进行垃圾回收后依然会将被引用对象回收掉。
public static void main(String[] args){
WeakReference<byte[]> soft = new WeakReference<>(new byte[1024*1024*10]);
System.out.println(soft.get());
//通知JVM进行垃圾回收
System.gc();
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(soft.get());
}
输出结果:
[B@2cfb4a64
null
虚引用PhantomReference
首先,虚引用是无法通过get方法来获取的。一个虚引用对象被回收时会被放在一个ReferenceQueue队列中,意思就是虚引用回收时会给出一个信号放在队列中。
ReferenceQueue<Object> rq = new ReferenceQueue<>();
Object obj = new Object();
PhantomReference<Object> phantomReference = new PhantomReference<>(obj,rq);
obj = null;
System.out.println("Reference: "+phantomReference.get());
System.gc();
Reference<Object> r = (Reference<Object>)rq.poll();
System.out.println("ReferenceQueue: "+r);
输出结果两个null。只有VM内存不足时才会回收这个虚引用,才会将其放在队列中,才能通过poll()获取到队列中的PhantomReference对象,而这个引用对象需要程序员自己进行特殊处理。
那问题来了,甭管G不GC我都拿不到它,那它有啥用?
其实它一般用来管理直接内存,我们的垃圾回收器是在JVM中管理内存的,如果我们从网络中下载一个文件保存在os的内存中,而 新版JVM不需要copy一份到jvm内存中,通过引用可以直接访问操作系统管理的内存,当我们回收这个虚引用时,则会在队列中放入这个引入对象,方便用来特殊处理。
来源:https://juejin.cn/post/7114569277914480648


猜你喜欢
- 出现此问题的原因一般都是jar包没有被扫描到;解决办法:1、在idea的设置里面如图:如果有多个jar包文件夹就都给加进来2、一般jdk版本
- 话不多说,请看代码:using System;using System.Web;using System.Drawing;using Sys
- 本文实例讲述了C#检测是否有u盘插入的方法。分享给大家供大家参考。具体如下:该C#代码可监控是否有u盘插入,同时可以监控其它驱动器的变化us
- Word中设置水印时,可加载图片设置为水印效果,但通常添加水印效果时,会对所有页面都设置成统一效果,如果需要对每一页或者某个页面设置不同的水
- 本文较为详细的讲述了在WCF数据访问中使用缓存提高Winform字段中文显示速度的方法,分享给大家供大家参考之用。具体方法如下:在我们开发基
- 1.1 概述分布式系统:分布式系统指由很多台计算机组成的一个整体!这个整体一致对外,并且处理同一请求!系统对内透明,对外不透明!内部的每台计
- 通过AIDL接口在进程间传递数据,记录在开发中遇到的一写问题AIDL支持数据类型如下:1. Java 的原生类型2. String 和Cha
- 使用DOM4J方式生成XML文件的步骤如下:引入JAR包通过DocumentHelper类的createDocument()创建Docume
- Springboot导入本地jar后 打包依赖无法加入1.本地jar包2.pom文件添加自定义jar包导入<!--自定义jar--&g
- 简介简单工厂模式 (Simple Factory) 又叫静态工厂方法(Static Factory Method)模式。简单工厂模式通常是定
- 在实际项目开发过程中,我们经常需要对某个对象或者某个集合中的元素进行排序,常用的两种方式是实现某个接口。常见的可以实现比较功能的接口有Com
- 一、前言(吐槽+煽情+简介) &n
- 简介Spring Security 是为了基于Spring的应用程序提供的声明式安全保护的安全性框架。Spring Security 提供了
- 这一篇我们说说Java线程Thread的interrupt中断机制。中断线程线程的thread.interrupt()方法是中断线程,将会设
- Android 中下拉菜单,即如html中的<select>,关键在于调用setDropDownViewResource方法,以
- 环境准备JDK 1.8,Springboot 2.1.3.RELEASE,spring-boot-starter-aop.2.1.4.REL
- java生成json时产生栈溢出错误环境java + hibernate +html本来,java中使用json事件很正常的事,但小心有的地
- 本文主要内容:•1、什么是Cookie•2、Cookie带来的好处•3、Cookie的主要方法 一、什么是Cookiecookie
- 参考链接亲测试以下版本成功激活附激活教程。idea下载链接(对应版本号下载):https://www.jetbrains.com/idea/
- 静默安装就是偷偷的把一个应用安装到手机上,就是屏蔽确认框,通过反射只能写个主要的代码,这个是在linux编译用到,因为静默安装需要调用系统服