专业汉语词典知识平台,分享汉字词语知识、历史文学知识解答!

励北网
励北网

引用类型有哪几种,Java引用类型详解

来源:小易整编  作者:小易  发布时间:2023-03-02 05:56
摘要:引用类型有哪几种,Java引用类型详解在Java中一切皆对象,对象的操作是通过该对象的引用(Reference)实现的Java中的引用类型有4种,分别是强引用、软引用、弱引用和虚引用(强、软、弱、虚)一、整体架构二、强引用(默认)Java中...

引用类型有哪几种,Java引用类型详解

引用类型有哪几种,Java引用类型详解

在Java中一切皆对象,对象的操作是通过该对象的引用(Reference)实现的

Java中的引用类型有4种,分别是强引用、软引用、弱引用和虚引用(强、软、弱、虚)

一、整体架构

二、强引用(默认)

Java中最常见的就是强引用,在把一个对象赋给一个引用变量时,这个引用变量就是一个强引用(Object obj = new Object(),obj就是一个强引用,obj在栈中,new Object()在堆中)

有强引用的对象一定为可达性状态

即便系统内存非常紧张,Java虚拟机宁愿抛出OutOfMemoryError(OOM)错误,使程序异常终止,也不会回收被强引用所引用的对象

强引用不会被垃圾回收机制直接回收,需要处理,因此强引用是造成内存泄露的主要原因

如果强引用对象不使用时,需要弱化从而使垃圾回收器能够回收,弱化的方式就是给引用变量赋为null,让其超出对象的生命周期范围,则垃圾回收器认为该对象不存在引用,这时就可以回收这个对象,具体什么时候收集取决于垃圾回收器算法

1、使用

public class StronglyReferenceTest {    public static void main(String[] args) throws IOException {        // obj1、obj2存放在栈中        Object obj1 = new Object();        Object obj2 = obj1;        obj1 = null;        System.gc();        // obj1为null被回收,但new Object()还是存放在堆中,被obj2强引用        System.out.println(obj1);    // 不会被垃圾回收        System.out.println(obj2);        // 阻塞main线程,给垃圾回收线程一点时间去执行       System.in.read();    } }

2、补充finalize()

finalize()是Object中的方法,当垃圾回收器将要回收对象所占内存之前被调用,即当一个对象被JVM宣告死亡时会先调用它finalize()方法

Java使用finalize()方法在垃圾回收器将对象从内存中清除出去之前做必要的清理工作

3、注意

(1)全局变量和局部变量

在一个方法的内部有一个强引用,这个引用保存在Java栈中,而真正的引用内容(Object)保存在Java堆中 ,当这个方法运行完成后,就会退出方法栈,则引用对象的引用数为0,这个对象会被回收

但是如果这个强引用是全局变量时,就需要在不用这个对象时赋值为null,因为强引用不会被垃圾回收

(2)内存溢出和内存泄漏

内存溢出 OutOfMemory,是指程序在申请内存时,没有足够的内存空间供其使用,出现OutOfMemoryError比如申请了一个Integer,但给它存了long才能存下的数,那就是内存溢出(强引用引发的错误)

内存泄露 MemoryLeak,是指程序在申请内存后,无法释放已申请的内存空间(强引用导致的结果)

大量的内存泄露会导致内存溢出(OOM)

(3)回收问题

对于一个普通的对象,如果没有其他的引用关系,只要超过了引用的作用域或者显示地将相应强引用赋值给null,一般认为就是可以被垃圾回收器收集了,具体还需要看垃圾回收的策略

三、软引用

软引用通过SoftReference类实现,如果一个对象只有软引用,则在系统内存空间不足时该对象将被回收

这一点可以很好地用来解决OOM的问题,并且这个特性很适合用来实现缓存:比如网页缓存、图片缓存等

1、使用

JVM配置:-Xms10M -Xmx25M -XX:+PrintGCDetails

import java.lang.ref.SoftReference; public class SoftReferenceTest {    public static void main(String[] args) {        // 10M        SoftReference<byte[]> softReference = new SoftReference<>(new byte[1024 * 1024 * 10]);        System.out.println(softReference.get());        // 手动回收        System.gc();        try {            Thread.sleep(500);        } catch (InterruptedException e) {            e.printStackTrace();        }        // 执行手动回收后,并没有回收        System.out.println(softReference.get());        // 15M 导致内存不足 自动回收        byte[] b = new byte[1024 * 1024 * 15];        System.out.println(softReference.get());    } }

2、缓存设计思路

用图片缓存为例,用一个HashMap来保存图片的路径和相应图片对象关联的软引用之间的映射关系,在内存不足时,JVM会自动回收这些缓存图片对象所占用的内存空间,从而有效地避免了OOM的问题

Map<String, SoftReference<Bitmap>> imageCache = new HashMap<>();

四、弱引用

弱引用通过WeekReference类实现,如果一个对象只有弱引用,则在垃圾回收过程中一定会被回收,也就是不管JVM的内存空间是否足够,都会回收弱引用类型的对象所占用的内存空间

弱引用的生命周期比软引用的生命周期更短

1、使用

import java.lang.ref.WeakReference; public class WeakReferenceTest {    public static void main(String[] args) {        WeakReference<Object> weakReference = new WeakReference<>(new Object());        System.out.println(weakReference.get());        System.gc();       // null        System.out.println(weakReference.get());    } }

2、ThreadLocal

Java里,每个线程(Thread)都有自己的ThreadLocalMap,里边存着自己私有的对象

Map的Entry里,key为ThreadLocal对象,value即为私有对象

static class Entry extends WeakReference<ThreadLocal<?>> {  Object value;  Entry(ThreadLocal<?> k, Object v) {      super(k);        value = v;    } }

每个Thread内部都维护一个ThreadLocalMap字典数据结构,字典的Key值是ThreadLocal,那么当某个ThreadLocal对象不再使用(没有其它地方再引用)时,每个已经关联了此ThreadLocal的线程怎么在其内部的ThreadLocalMap里做清除此资源呢?

JDK中的ThreadLocalMap没有继承java.util.Map类,而是自己实现了一套专门用来定时清理无效资源的字典结构

其内部存储实体结构Entry<ThreadLocal, T>继承自java.lan.ref.WeakReference,这样当ThreadLocal不再被引用时,因为弱引用机制原因,当JVM发现内存不足时,会自动回收弱引用指向的实例内存,即其线程内部的ThreadLocalMap会释放其对ThreadLocal的引用从而让JVM回收ThreadLocal对象

这里是重点强调下,是回收对ThreadLocal对象,而非整个Entry,所以线程变量中的值T对象还是在内存中存在的,所以内存泄漏的问题还没有完全解决

调用ThreadLocal.get()或者ThreadLocal.set(T)时都会定期执行回收无效的Entry操作

3、WeakHashMap

import java.util.HashMap; import java.util.Map; import java.util.WeakHashMap; public class WeakHashMapTest {    public static void main(String[] args) {        Map<Integer, String> hashMap =new HashMap<>();        Integer key1 = new Integer("1");        String value1 = "HashMap";        hashMap.put(key1, value1);        System.out.println(hashMap);        key1 = null; // 只跟new Integer("1")有关,跟Map无关系,不影响 HashMap        System.out.println(hashMap);        System.gc(); // 不影响 HashMap        System.out.println(hashMap);        System.out.println("----------");        Map<Integer, String> weakHashMap =new WeakHashMap<>();        Integer key2 = new Integer("2");        String value2 = "WeakHashMap";        weakHashMap.put(key2, value2);        System.out.println(weakHashMap);        key2 = null; // 只跟new Integer("2")有关,跟Map无关系,不影响 WeakHashMap        System.out.println(weakHashMap);        System.gc(); // 影响 WeakHashMap        System.out.println(weakHashMap);    } }

4、ReferenceQueue

import java.lang.ref.ReferenceQueue; import java.lang.ref.WeakReference; public class ReferenceQueueTest {    public static void main(String[] args) {        Object obj = new Object();        ReferenceQueue<Object> referenceQueue = new ReferenceQueue<>();        WeakReference<Object> weakReference = new WeakReference<>(obj, referenceQueue);        System.out.println(obj);        System.out.println(weakReference.get());        System.out.println(referenceQueue.poll()); // null        System.out.println("----------");        obj = null;        System.gc();        try {            Thread.sleep(500);        } catch (InterruptedException e) {            e.printStackTrace();        }        System.out.println(obj); // null        System.out.println(weakReference.get()); // null        System.out.println(referenceQueue.poll());    } }

五、虚引用

与其他三种引用都不同,虚引用并不会决定对象的生命周期。如果一个对象仅持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被回收

PhantomReference的get方法总是返回null,因此无法访问对应的引用对象,它的意义在于说明一个对象已经进入finalization阶段,可以被垃圾回收器回收,用来实现比finalization机制更灵活的回收操作

虚引用通过PhantomReference类实现,虚引用和引用队列联合使用

虚引用主要用来跟踪对象被垃圾回收的活动。虚引用与软引用和弱引用的一个区别在于:虚引用必须和引用队列(ReferenceQueue)联合使用

当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会在回收对象的内存之前,把这个虚引用加入到与之关联的引用队列中

设置虚引用关联的唯一目的就是在这个对象被回收的时候,收到一个系统通知或者后续添加进一步的处理

Object object = new Object(); ReferenceQueue queue = new ReferenceQueue (); PhantomReference pr = new PhantomReference (object, queue);

六、总结

当垃圾回收器回收时,某些对象会被回收,某些不会被回收

垃圾回收器会从根对象Object来标记存活的对象,然后将某些不可达的对象和一些引用的对象进行回收

引用类型被垃圾回收时间用途生存时间
强引用从来不会对象的一般状态JVM停止运行时终止
软引用当内存不足时对象缓存内存不足时终止
弱引用正常垃圾回收时对象缓存垃圾回收后终止
虚引用正常垃圾回收时跟踪对象的垃圾回收垃圾回收后终止

本文地址:百科问答频道 https://www.neebe.cn/wenda/907993.html,易企推百科一个免费的知识分享平台,本站部分文章来网络分享,本着互联网分享的精神,如有涉及到您的权益,请联系我们删除,谢谢!


百科问答
小编:小易整编
相关文章相关阅读
  • 用java开发的游戏有哪些 java架构开发的游戏推荐2023

    用java开发的游戏有哪些 java架构开发的游戏推荐2023

    java是一种非常实用的计算机语言,正因如此也把它使用在了游戏设计中,那么用java开发的游戏有哪些呢?本期小编就将带各位小伙伴了解一下相关的内容,这项有用的技术被应用到各种不同种类的游戏制作和设计中,增加了游戏的体验感,这些游戏都具有自己...

  • 如何安装java,java安装教程

    如何安装java,java安装教程

    如何安装java,java安装教程一·下载JAVA安装包并安装1.首先去官网下载JAVA安装包,JAVA安装包下载地址:https://www.oracle点com/technetwork/java/javase/downloads/ind...

  • classpath环境变量作用,Java环境变量classpath的作用

    classpath环境变量作用,Java环境变量classpath的作用

    classpath环境变量作用,Java环境变量classpath的作用环境变量环境变量(environmentvariables)一般是指在操作系统中用来指定操作系统运行环境的一些参数,如:临时文件夹位置和系统文件夹位置等。环境变量是在操...

  • 如何数组合并,JavaScript合并数组的三种方法

    如何数组合并,JavaScript合并数组的三种方法

    如何数组合并,JavaScript合并数组的三种方法数组作为一种数据结构,表示索引项的有序集合。经常会使用到数组,尤其是将多个数组进行合并,比如将数组[1,2,3]和数组[4,5,6]合并,最终得到数组[1,2,3,4,5,6]。数组的合并...

  • 怎么解析xml文件,java解析xml文件的几种方式

    怎么解析xml文件,java解析xml文件的几种方式

    怎么解析xml文件,java解析xml文件的几种方式一、为什么使用xml文件便于不同应用程序之间通信。便于不同平台之间通信。便于不同平台之间数据共享。二、读取xml的方式xml测试文件内容如下:

  • 回到顶部如何实现,JavaScript实现回到顶部功能的五种方法

    回到顶部如何实现,JavaScript实现回到顶部功能的五种方法

    回到顶部如何实现,JavaScript实现回到顶部功能的五种方法回到顶部的功能现在基本上是网页的标配了,当你已经浏览到页面底部时,一键返回顶部的功能确实非常方便。随着用户习惯的养成,这个功能都是页面必备的。那么作为一个前端开发者,我们如何实...

  • java虚拟机是什么,深入理解java虚拟机

    java虚拟机是什么,深入理解java虚拟机

    java虚拟机是什么,深入理解java虚拟机文章目录一、Java虚拟机是什么二、为什么需要了解Java虚拟机三、JavaJDK的迭代历史四、Java虚拟机发展史与种类五、Java虚拟机规范六、Java虚拟机语言无关性七、Java虚拟机的组成...

  • java入门基础知识,java入门教程【0基础自学】

    java入门基础知识,java入门教程【0基础自学】

    java入门基础知识,java入门教程源代码组织方式Java程序由package+class组成,package对应目录的相对路径,class对应文件,如E:\Workspaces\MyEclipse10\JavaStudy\src\com...

  • 周排行
  • 月排行
  • 年排行

精彩推荐