你知道 Java 有哪些引用吗?

java · 浏览次数 : 0

小编点评

**前言** 引用计数法和可达性算法都是用于判断对象是否要回收的算法,但它们与对象的生命周期和内存使用无关。本文将介绍 Java 中四种引用类型及其在内存管理中的作用。 **一、概述** **强引用** 强引用是最常见的也是默认的引用类型。它直接访问目标对象,即使对象已经回收,强引用仍然有效。 **软引用** 软引用描述一些还有用,但非必需的对象。在系统内存不足时,软引用会将其列入回收范围之中进行第二次回收。 **弱引用** 弱引用也是用于描述非必需对象的引用类型。当发现弱引用时,无论系统内存使用是否充足,都会回收掉只被弱引用关联的对象。 **虚引用** 虚引用是最弱的引用类型。一个对象是否有虚引用的存在,完全不会决定对象的生命周期。 **四种引用类型的比较** | 引用类型 | 描述 | 作用 | |---|---|---| | 强引用 | 直接访问目标对象 | 对象指向该对象的强引用 | | 软引用 | 描述一些还有用,但非必需的对象 | 对象被软引用关联时列入回收范围 | | 弱引用 | 用于描述非必需对象,在GC时会被回收 | 当发现弱引用时回收掉只被弱引用关联的对象 | | 虚引用 | 不能单独使用,必须和引用队列一起使用 | 对象被虚引用变量引用时加入引用队列 | **结论** 在内存管理中,强引用、软引用、弱引用和虚引用在不同的场景中发挥着关键角色。了解这些引用类型有助于我们优化对象的生命周期和内存使用。

正文

前言

判断对象是否要回收有引用计数法和可达性算法两种方式,无论哪种都离不开引用,本文将介绍Java的四种引用。


一、概述

image.png

image.png

二、详解

1. 强引用

概述

在Java程序中,强引用是最常见的也是默认的。new了一个对象,并将其指向一个变量,这个变量就成为指向该对象的一个强引用。

特点

  1. 强引用可以直接访问目标对象;
  2. 强引用所指向的对象在任何时候都不会被系统回收;
  3. 强引用可能导致内存泄漏。

实现方式

Object obj = new Object()	//这里的obj就是一个强引用
Object obj = new Object(); // 声明强引用
SoftReference<Object> sf = new SoftReference<>(obj);
obj = null; //销毁强引用
Object obj = new Object(); // 声明强引用
WeakReference<Object> wf = new WeakReference<>(obj);
obj = null; //销毁强引用
Object obj = new Object(); // 声明强引用
ReferenceQueue phantomQueue = new ReferenceQueue();
PhantomReference<Object> pf = new PhantomReference<>(obj, phantomQueue);
obj = null;

2. 软引用

概述

软引用是用来描述一些还有用,但非必需的对象。只被软引用关联着的对象,在系统将要发生内存溢出异常前,会把这些对象列进回收范围之中进行第二次回收,如果这次回收还没有足够的内存,才会抛出内存溢出异常。

特点

  1. 软引用所指向的对象,内存溢出前才被系统回收;
  2. 软引用被回收后还没有足够的内存,仍会抛出内存溢出异常;
  3. GC 决定收回软可达对象时,会清理软引用,并可选地把引用存放到一个引用队列(Reference Queue)。

场景

软引用通常用来实现内存敏感的缓存。比如:可以使用软引用来缓存最近使用的图片或文本,一旦内存不足,垃圾回收器就会回收这些对象,从而释放内存。

实现方式

Object obj = new Object(); // 声明强引用
SoftReference<Object> sf = new SoftReference<>(obj);
obj = null; //销毁强引用

3. 弱引用

概述

弱引用也是用来描述那些非必需对象,但是在系统GC时,只要发现弱引用,不管系统堆空间使用是否充足,都会回收掉只被弱引用关联的对象。 (但是,由于垃圾回收器的线程通常优先级很低,因此,并不一定能很快地发现持有弱引用的对象。在这种情况下,弱引用对象可以存在较长的时间。)

特点

弱引用所指向的对象,被发现就会被系统回收;

场景

  1. 缓存中存放的一些临时的数据。如,ThreadLocal;
  2. 多线程中经常被用来监控对象是否被垃圾回收器标记。

实现方式

Object obj = new Object(); // 声明强引用
WeakReference<Object> wf = new WeakReference<>(obj);
obj = null; //销毁强引用

4. 虚引用

概述

所有引用类型中最弱的一个。一个对象是否有虚引用的存在,完全不会决定对象的生命周期。

特点

  1. 不能单独使用,虚引用必须和引用队列一起使用;
  2. 一个对象只被虚引用变量引用时,垃圾回收器会将该对象加入引用队列中;
  3. 无法通过虚引用来获取被引用的对象(当试图通过虚引用的get()方法取得对象时,总是null)。

场景

在回收该对象之前,虚引用变量将被放入引用队列中,因此通常用于在对象被回收时执行必要的清理工作。例如:

  1. 关闭数据库连接或释放资源在并发编程中;
  2. 实现一些高级的对象生命周期管理,例如,对象池和线程池等。(追踪对象的生命周期,并在对象不再使用时及时清理它们,从而保证系统的可靠性和性能)

实现方式

Object obj = new Object(); // 声明强引用
ReferenceQueue phantomQueue = new ReferenceQueue(); //须和引用队列一起使用
PhantomReference<Object> pf = new PhantomReference<>(obj, phantomQueue);
obj = null;

与你知道 Java 有哪些引用吗?相似的内容:

你知道 Java 有哪些引用吗?

判断对象是否要回收有引用计数法和可达性算法两种方式,无论哪种都离不开引用,本文将介绍Java的四种引用。

买彩票能中大奖?用Java盘点常见的概率悖论 | 京东云技术团队

引言 《双色球头奖概率与被雷劈中的概率哪个高?》 《3人轮流射击,枪法最差的反而更容易活下来?》 让我们用Java来探索ta们! 悖论1:著名的三门问题 规则描述:你正在参加一个游戏节目,你被要求在三扇门中选择一扇:其中一扇后面有一辆车;其余两扇后面则是山羊。你选择了一道门,假设是一号门,然后知道门

解放双手!ChatGPT助力编写JAVA框架

亲爱的Javaer们,在平时编码的过程中,你是否曾想过编写一个Java框架去为开发提效?但是要么编写框架时感觉无从下手,不知道从哪开始。要么有思路了后对某个功能实现的技术细节不了解,空有想法而无法实现。如果你遇到了这些问题,看完这篇文章你也能用ChatGPT编写一个简单的JAVA框架。

[转帖]JVM系列之:你知道Java有多少种内存溢出吗

本文为《深入学习 JVM 系列》第二十五篇文章 Java内存区域 关于这部分内容大多来源于《深入理解Java虚拟机》一书。 Java 运行时数据区域(JDK8)如下图所示: 关于上述提到的线程共享和线程隔离区域,下图做详细讲解: 程序计数器 程序计数器是一块较小的内存空间,可以看作是当前线程所执行的

当面试官问出“Unsafe”类时,我就知道这场面试废了,祖坟都能给你问出来!

一、写在开头 依稀记得多年以前的一场面试中,面试官从Java并发编程问到了锁,从锁问到了原子性,从原子性问到了Atomic类库(对着JUC包进行了刨根问底),从Atomic问到了CAS算法,紧接着又有追问到了底层的Unsafe类,当问到Unsafe类时,我就知道这场面试废了,这似乎把祖坟都能给问冒烟

面试官:什么是双亲委派模型?

本文已经收录进 JavaGuide(「Java学习+面试指南」一份涵盖大部分 Java 程序员所需要掌握的核心知识。) 参加过校招面试的同学,应该对这个问题不陌生。一般提问 JVM 知识点的时候,就会顺带问你双亲委派模型(别扭的翻译。。。)。 就算是不准备面试,学习双亲委派模型对于我们也非常有帮助。

Java面试题:你知道Spring的IOC吗?那么,它为什么这么重要呢?

Spring的IOC(控制反转)是一种设计模式,它允许开发者将对象的创建和管理交给Spring框架来完成。在Spring中,IOC允许开发者将对象依赖关系从代码中分离出来,从而使代码更加灵活、可重用和易于管理。 IoC 全称Inverse of Control(反向控制或控制反转)。 在类和类之间存

面试官:素有Java锁王称号的‘StampedLock’你知道吗?我:这什么鬼?

一、写在开头 我们在上一篇写ReentrantReadWriteLock读写锁的末尾留了一个小坑,那就是读写锁因为写锁的悲观性,会导致 “写饥饿”,这样一来会大大的降低读写效率,而今天我们就来将此坑填之!填坑工具为:StampedLock,一个素有Java锁王称号的同步类,也是在 java.util

还不知道如何在java中终止一个线程?快来,一文给你揭秘

简介 工作中我们经常会用到线程,一般情况下我们让线程执行就完事了,那么你们有没有想过如何去终止一个正在运行的线程呢? 今天带大家一起来看看。 Thread.stop被禁用之谜 问道怎么终止一个线程,可能大多数人都知道可以调用Thread.stop方法。 但是这个方法从jdk1.2之后就不推荐使用了,

10分钟带你徒手做个Java线程池

摘要:花10分钟开发一个极简版的Java线程池,让小伙伴们更好的理解线程池的核心原理。 本文分享自华为云社区《放大招了,冰河带你10分钟手撸Java线程池,yyds,赶快收藏吧》,作者:冰 河。 Java线程池核心原理 看过Java线程池源码的小伙伴都知道,在Java线程池中最核心的类就是Threa