Java强软弱虚四大引用

2024-01-21 12:04
文章标签 java 引用 四大 软弱

本文主要是介绍Java强软弱虚四大引用,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

  • 一、强引用
  • 二、软引用
  • 三、弱引用
  • 四、虚引用


提示:以下是本篇文章正文内容,下面案例可供参考

一、强引用

在Java中,强引用(Strong Reference)是最常见的引用类型。当我们创建一个对象并将其赋值给一个变量时,实际上就是创建了一个强引用。这意味着只要这个引用变量还存在,垃圾回收器就不会回收它所引用的对象。(除非等于null)

简单来说日常使用的大部分都是强引用,即使OOM也不回收,所以往往是导致内存泄露的元凶

代码如下(示例):

public class Test {public static void main(String[] args) throws Throwable {/*** 虚拟机配置选项* VM Options :-XX:+PrintGCDetails -Xms10m -Xmx10m* -XX:+PrintGCDetails:打印 GC 的详细信息* -Xms10m:设置初始化堆空间大小为 10m* -Xmx10m:设置最大堆空间大小为 10m*/// 强引用byte[] bytes = new byte[4 * 1024 * 1024];// 调用 GCSystem.gc();}
}

输出结果(如下):

可以看出 bytes 并没有存储任何数据,仅仅是开辟空间,但是 GC 后仍然存在

在这里插入图片描述

在这里插入图片描述


二、软引用

在Java中,软引用(SoftReference)是一种特殊类型的引用,它比强引用弱,但比弱引用强。当系统内存不足时,即 JVM 空间即将耗尽,垃圾回收器会优先清理那些只被软引用关联的对象。如果一个对象只剩下软引用,那么在内存充足的情况下,该对象不会被回收;但在内存不足时,这个软引用指向的对象会被垃圾回收器回收以释放内存。
软引用通常用于实现内存敏感的缓存,例如图片缓存。当系统内存紧张时,这些缓存可以被自动清除,从而避免了 OutOfMemoryError 异常的发生,同时,在内存资源相对充足时,又能保持缓存的功能,提高程序性能。

简单来说,就是内存不足是才回收

代码如下(示例):

public class Test {public static void main(String[] args) throws Throwable {/*** 虚拟机配置选项* VM Options :-XX:+PrintGCDetails -Xms10m -Xmx10m* -XX:+PrintGCDetails:打印 GC 的详细信息* -Xms10m:设置初始化堆空间大小为 10m* -Xmx10m:设置最大堆空间大小为 10m*/// 软引用Map<String, SoftReference<byte[]>> map = new HashMap<>();// 最大 10m 的堆空间肯定装不 24m 的数组,所以 JVM 会自动 GC 回收map.put("bytes1", new SoftReference<>(new byte[6 * 1024 * 1024]));map.put("bytes2", new SoftReference<>(new byte[6 * 1024 * 1024]));map.put("bytes3", new SoftReference<>(new byte[6 * 1024 * 1024]));// 强引用数组,无法回收byte[] bytes2 = new byte[6 * 1024 * 1024];}
}

输出结果(如下):

可以看出JVM多次调用 GC 回收软引用
在这里插入图片描述


三、弱引用

在Java中,弱引用(WeakReference)是一种特殊的引用类型,它代表的对象可被垃圾回收器在任何时候回收,即使该对象仍然有弱引用存在。相比于强引用(普通引用),只要强引用还在,垃圾回收器就不会回收该对象;而软引用和弱引用都允许在内存不足时回收其引用的对象,但软引用会在系统内存尚充足的情况下尽可能保留对象,而弱引用则不考虑当前内存状况。
弱引用的典型使用场景是在缓存或者映射关系中,当主要持有对象的强引用消失后,即使还有其他地方通过弱引用关联到这个对象,也依然会被垃圾回收器视为无用对象并进行回收。

简单来说,就是只要GC就会回收

代码如下(示例):

public class Test {public static void main(String[] args) {/*** 虚拟机配置选项* VM Options :-XX:+PrintGCDetails* -XX:+PrintGCDetails:打印 GC 的详细信息*/// 弱引用// 开辟一个很小的数组WeakReference<byte[]> weakReference = new WeakReference<byte[]>(new byte[10]);// GC 前System.out.printf(Arrays.toString(weakReference.get()));System.out.println();System.gc();// GC 后System.out.printf(Arrays.toString(weakReference.get()));System.out.println();}
}

输出结果(如下):

可以看出这个很小的数组在GC后直接没了,即使空间充足

在这里插入图片描述


四、虚引用

虚引用,顾名思义,就是形同虚设,与其他几种引用都不同,虚引用并不会决定对象的生命周期。如果一个对象仅持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收器回收,它不能单独使用也不能通过它访问对象,虚引用必须和引用队列(ReferenceQueue)联合使用。
虚引用的主要作用是跟踪对象被垃圾回收的状态。仅仅是提供了一种确保对象被finalize以后,做某些事情的机制。
PhantomReference的get方法总是返回null,因此无法访问对应的引用对象。其意义在于说明一个对象已经进入finalization阶段,可以被gc回收,用来实现比finalization机制更灵活的回收操作。换句话说,设置虚引用关联的唯一目的,就是在这个对象被收集器回收的时候收到一个系统通知或者后续添加进一步的处理。Java技术允许使用finalize()方法在垃圾收集器将对象从内存中清除出去之前做必要的清理工作。

源代码如下:

public class PhantomReference<T> extends Reference<T> {/*** Returns this reference object's referent.  Because the referent of a* phantom reference is always inaccessible, this method always returns* <code>null</code>.** @return  <code>null</code>*/public T get() {return null;}/*** Creates a new phantom reference that refers to the given object and* is registered with the given queue.** <p> It is possible to create a phantom reference with a <tt>null</tt>* queue, but such a reference is completely useless: Its <tt>get</tt>* method will always return null and, since it does not have a queue, it* will never be enqueued.** @param referent the object the new phantom reference will refer to* @param q the queue with which the reference is to be registered,*          or <tt>null</tt> if registration is not required*/public PhantomReference(T referent, ReferenceQueue<? super T> q) {super(referent, q);}}

简单来说就是虚引用不存储任何东西,且必须配合引用队列使用,它唯一的作用就是监控绑定的对象是否被回收

代码如下(示例):


public class Test {public static void main(String[] args) {// 虚引用// 作用:监控对象的回收情况// 要监控的对象Object o1 = new Object();// 引用队列ReferenceQueue<Object> referenceQueue = new ReferenceQueue<>();// 虚引用绑定对象和引用队列PhantomReference<Object> phantomReference = new PhantomReference<>(o1, referenceQueue);// 回收前的被监控的对象System.out.println("回收前的被监控的对象: " + o1);// 虚引用地址System.out.println("虚引用地址: " + phantomReference);// 源码可知,总是返回 nullSystem.out.println("虚引用的返回值: " + phantomReference.get());// 所以队列也返回 nullSystem.out.println("引用队列的返回值: " + referenceQueue.poll());System.out.println("====================");// 置空监控的对象o1 = null;// 回收对象System.gc();// 监控的对象System.out.println("回收后的对象: " +o1);// 虚引用地址System.out.println( "虚引用地址: " + phantomReference);// 源码可知,总是返回 nullSystem.out.println("虚引用的返回值: " + phantomReference.get());// 重点!!!!!// 引用队列中存储了虚引用,说明该对象被回收了// 这就是虚引用的唯一目的,即 gc 后将自身加入到引用队列System.out.println("引用队列的返回值: " + referenceQueue.poll());}
}

输出结果(如下):

在这里插入图片描述


这篇关于Java强软弱虚四大引用的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/629481

相关文章

JVM 的类初始化机制

前言 当你在 Java 程序中new对象时,有没有考虑过 JVM 是如何把静态的字节码(byte code)转化为运行时对象的呢,这个问题看似简单,但清楚的同学相信也不会太多,这篇文章首先介绍 JVM 类初始化的机制,然后给出几个易出错的实例来分析,帮助大家更好理解这个知识点。 JVM 将字节码转化为运行时对象分为三个阶段,分别是:loading 、Linking、initialization

Spring Security 基于表达式的权限控制

前言 spring security 3.0已经可以使用spring el表达式来控制授权,允许在表达式中使用复杂的布尔逻辑来控制访问的权限。 常见的表达式 Spring Security可用表达式对象的基类是SecurityExpressionRoot。 表达式描述hasRole([role])用户拥有制定的角色时返回true (Spring security默认会带有ROLE_前缀),去

浅析Spring Security认证过程

类图 为了方便理解Spring Security认证流程,特意画了如下的类图,包含相关的核心认证类 概述 核心验证器 AuthenticationManager 该对象提供了认证方法的入口,接收一个Authentiaton对象作为参数; public interface AuthenticationManager {Authentication authenticate(Authenti

Spring Security--Architecture Overview

1 核心组件 这一节主要介绍一些在Spring Security中常见且核心的Java类,它们之间的依赖,构建起了整个框架。想要理解整个架构,最起码得对这些类眼熟。 1.1 SecurityContextHolder SecurityContextHolder用于存储安全上下文(security context)的信息。当前操作的用户是谁,该用户是否已经被认证,他拥有哪些角色权限…这些都被保

Spring Security基于数据库验证流程详解

Spring Security 校验流程图 相关解释说明(认真看哦) AbstractAuthenticationProcessingFilter 抽象类 /*** 调用 #requiresAuthentication(HttpServletRequest, HttpServletResponse) 决定是否需要进行验证操作。* 如果需要验证,则会调用 #attemptAuthentica

Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密》 《Spring-Security-入门(四):自定义-Filter》 《Spring-Security-入门(五):在 Sprin

Java架构师知识体认识

源码分析 常用设计模式 Proxy代理模式Factory工厂模式Singleton单例模式Delegate委派模式Strategy策略模式Prototype原型模式Template模板模式 Spring5 beans 接口实例化代理Bean操作 Context Ioc容器设计原理及高级特性Aop设计原理Factorybean与Beanfactory Transaction 声明式事物

Java进阶13讲__第12讲_1/2

多线程、线程池 1.  线程概念 1.1  什么是线程 1.2  线程的好处 2.   创建线程的三种方式 注意事项 2.1  继承Thread类 2.1.1 认识  2.1.2  编码实现  package cn.hdc.oop10.Thread;import org.slf4j.Logger;import org.slf4j.LoggerFactory

JAVA智听未来一站式有声阅读平台听书系统小程序源码

智听未来,一站式有声阅读平台听书系统 🌟&nbsp;开篇:遇见未来,从“智听”开始 在这个快节奏的时代,你是否渴望在忙碌的间隙,找到一片属于自己的宁静角落?是否梦想着能随时随地,沉浸在知识的海洋,或是故事的奇幻世界里?今天,就让我带你一起探索“智听未来”——这一站式有声阅读平台听书系统,它正悄悄改变着我们的阅读方式,让未来触手可及! 📚&nbsp;第一站:海量资源,应有尽有 走进“智听

高效录音转文字:2024年四大工具精选!

在快节奏的工作生活中,能够快速将录音转换成文字是一项非常实用的能力。特别是在需要记录会议纪要、讲座内容或者是采访素材的时候,一款优秀的在线录音转文字工具能派上大用场。以下推荐几个好用的录音转文字工具! 365在线转文字 直达链接:https://www.pdf365.cn/ 365在线转文字是一款提供在线录音转文字服务的工具,它以其高效、便捷的特点受到用户的青睐。用户无需下载安装任何软件,只