一、引言

  前面我们学习了JVM的垃圾回收机制,我们知道了垃圾回收是JVM的自发行为;虽然我们可以通过System.gc() 或Runtime.getRuntime().gc()进行显式调用垃圾回收 ,但JVM可以屏蔽掉显式的垃圾回收调用,且JVM也有自己的一套垃圾回收机制,那么我们有没有什么办法可以“告诉”JVM,哪些对象是可以使用以后回收,哪些对象保留呢?这里就要说一下JAVA对象的引用类型了。

二、对象引用的简单介绍

  • 强引用:无论内存是否足够,不会回收。
  • 软引用:内存不足时,回收该引用关联的对象。
  • 弱引用:垃圾回收时,无论内存是否足够,都会回收。
  • 虚引用:任何时候都可能被垃圾回收器回收。

Java中提供这四种引用类型主要有两个目的:

    • 1、让程序员通过代码的方式决定某些对象的生命周期
    • 2、第二是有利于JVM进行垃圾回收。

三、对象引用代码示例

强引用

  强引用是我们使用的最广泛,也是最普遍的一种引用类型,常见的创建对象的方式就使用的强引用:

//1、强引用示例
String str = new String();

特点:

  • 只要某个对象是强引用的,或者有强引用与之关联,JVM必定不会回收这个对象
  • 内存不足的情况下,JVM会抛出OutOfMemory错误
  • 需要回收时,可以显式设置此对象为null,JVM就会自行在垃圾回收发生时去回收此对象

软引用

  软引用是用来描述一些有用但并不是必需的对象,在Java中用java.lang.ref.SoftReference类来表示。对于软引用关联着的对象,只有在内存不足的时候JVM才会回收该对象:

//2、软引用示例
SoftReference<String> softStr = new SoftReference<String>(new String("这是一个软引用类型的字符串对象"));
System.out.println(softStr.get());

  软引用相对与强引用来说,比较好的解决了OOM【Out Of Memory】的问题,可以把一些有用的数据,但又不是核心的内容通过软引用的形式来设置,那么当内存不足时就可以回收释放空间了。常见应用如软引用一个图片对象等。

特点:

  • SoftReference类包裹引用
  • JVM内存不足时会回收【存在强引用关联时不回收】

弱引用

  弱引用也是用来描述一些有用但并不是必需的对象,在Java中用java.lang.ref.WeakReference类来表示。对于弱引用关联着的对象,当JVM进行垃圾回收时,无论内存是否充足,都会回收:

//3、弱引用示例
WeakReference<String> weekStr = new WeakReference<String>(new String("这是一个弱引用类型的字符串对象"));
System.out.println(weekStr.get());
//显式调用JVM垃圾回收
System.gc();
//输出弱引用的内容【此时会输出null,因为在显式调用垃圾回收的时候,弱引用对象的内容已经被回收了】
System.out.println(weekStr.get());

  PS:如果弱引用对象有对应的强引用关联,那么垃圾回收时是不会回收此弱引用的【软引用也类似】

特点:

  • WeakReference类包裹引用
  • JVM无论内存充足与否均会在垃圾回收时回收【存在强引用关联时不回收】

虚引用

  虚引用不影响对象的生命周期。在java中用java.lang.ref.PhantomReference类表示。如果一个对象与虚引用关联,则跟没有引用与之关联一样,在任何时候都可能被垃圾回收器回收

//4、虚引用示例
//4.1、创建一个引用队列【虚引用必须跟引用队列关联使用】
ReferenceQueue<String> queue = new ReferenceQueue<String>();
//4.2、创建一个虚引用包裹一个字符串对象的引用地址
PhantomReference<String> phantomStr = new PhantomReference<String>(new String("这是一个虚引用类型的字符串对象"), queue);
//4.3、输出引用内容【结果发现输出为null】
System.out.println(phantomStr.get());

特点:

  • PhantomReference类包裹引用
  • 任何时候都可能被垃圾回收器回收
  • 必须跟引用队列关联使用

引用队列(ReferenceQueue)

作用:

  • 用于监听Reference所指向的对象是否已经被垃圾回收

使用场景:

  • 当大量使用各种引用(Reference)来包裹实例对象时,虽然引用(Reference)指向的对象可能被回收了,但Reference本身也是个对象,所以也需要回收,这时就需要使用ReferenceQueue了。

回收模式上的区别:

  • 当SoftReference或WeakReference的get()加入ReferenceQueue或get()返回null时,仅是表明其指示的对象已经进入垃圾回收流程,此时对象不一定已经被垃圾回收。
  • 当PhantomReference加入ReferenceQueue时,则表明对象需要且已被回收【PS:所以虚引用的例子的4.3步骤,调用get方法时返回会为null】。

JVM学习(五)对象的引用类型的更多相关文章

  1. JavaScript之面向对象学习五(JS原生引用类型Array、Object、String等等)的原型对象介绍

    1.原型模式的重要性不仅仅体现在创建自定义类型方面,就连所有的原生的引用类型(Obejct.Array.String等等)都在构造函数的原型上定义方法和属性.如下代码可以证明: alert(typeo ...

  2. JVM学习03_new对象的内存图讲解,以及引出static方法(转)

    目录 -=-讲解对象创建过程中,-=-堆内存和栈内存的情况 -=-构造函数对类对象的成员变量的初始化过程 -=-构造函数出栈 -=-类的方法在不访问类对象的成员变量时造成的内存资源浪费怎么解决? -= ...

  3. JVM学习五:JVM之类加载器之编译常量和主动使用

    在学习了前面几节的内容后,相信大家已经对JAVA 虚拟机 加载类的过程有了一个认识和了解,那么本节,我们就继续进一步巩固前面所学知识和特殊点. 一.类的初始化回顾 类在初始化的时候,静态变量的声明语句 ...

  4. JVM学习之对象的状态

    堆中存放着几乎所有的对象实例,垃圾收集器在堆堆进行回收前,首先要确定这些对象哪些还“活着”,哪些已经“死去”.方法有如下两种: (1)引用计数法 算法思想:为对象添加一个引用计数器,每当有一个地方引用 ...

  5. Hibernate基础学习(五)—对象-关系映射(下)

    一.单向n-1 单向n-1关联只需从n的一端可以访问1的一端. 域模型: 从Order到Customer的多对一单向关联.Order类中定义一个Customer属性,而在Customer类不用存放Or ...

  6. jvm学习记录-对象的创建、对象的内存布局、对象的访问定位

    简述 今天继续写<深入理解java虚拟机>的对象创建的理解.这次和上次隔的时间有些长,是因为有些东西确实不好理解,就查阅各种资料,然后弄明白了才来做记录. (此文中所阐述的内容都是以Hot ...

  7. JVM学习记录-对象已死吗

    前言 先来回顾一下,在jvm运行时数据区,分为两部分,一个部分是线程共享区,主要包括堆和方法区,另一部是线程私有区分包括本地方法栈,虚拟机栈和程序计数器.在线程私有部分的三个区域是随着线程生和灭的.栈 ...

  8. JVM学习--(五)垃圾回收器

    上一篇我们介绍了常见的垃圾回收算法,不同的算法各有各的优缺点,在JVM中并不是单纯的使用某一种算法进行垃圾回收,而是将不同的垃圾回收算法包装在不同的垃圾回收器当中,用户可以根据自身的需求,使用不同的垃 ...

  9. JVM学习-之对象的创建和内存分配

    最近看JVM内存模型,看了很多文章,大都讲到JVM将内存区域划分分:Mehtod-Area(No heap) 方法区,Heap(堆)区,Program Counter Register(程序计数器), ...

  10. JVM学习五:性能监控工具

    一.系统性能监控 系统性能工具用于确定系统运行的整体状态,基本定位问题所在. Linux – uptime • 系统时间 • 运行时间 n 例子中为7分钟 • 连接数 n 每一个终端算一个连接 • 1 ...

随机推荐

  1. PHP、JS一些用法

    PHP去除小数点后面的0,保留非零 floatval($num) PHP转数组var d = eval(数组d); PHP字符串转数组 $row['0'] = explode(";" ...

  2. 牛客网PAT练习场-A+B和C

    签到题 .题目地址:https://www.nowcoder.com/pat/6/problem/4077 #include<iostream> #include<cstdio> ...

  3. Java多线程_生产者消费者模式1

    生产者消费者模型       具体来讲,就是在一个系统中,存在生产者和消费者两种角色,他们通过内存缓冲区进行通信,生产者生产消费者需要的资料,消费者把资料做成产品.生产消费者模式如下图.(图片来自网络 ...

  4. 学习一下 JVM (二) -- 学习一下 JVM 中对象、String 相关知识

    一.JDK 8 版本下 JVM 对象的分配.布局.访问(简单了解下) 1.对象的创建过程 (1)前言 Java 是一门面向对象的编程语言,程序运行过程中在任意时刻都可能有对象被创建.开发中常用 new ...

  5. 技术揭秘:华为云DLI背后的核心计算引擎

    摘要:介绍隐藏在华为云数据湖探索服务背后的核心计算引擎Spark,玩转DLI,,轻松完成大数据的分析处理. 本文主要给大家介绍隐藏在华为云数据湖探索服务(后文简称DLI)背后的核心计算引擎——Spar ...

  6. 使用echarts 轻松搞定各种后台数据统计

    之前接到老大一个需求,需要将公私生态系统构建一个日志系统,统计公有云.私有云还有其他工具平台(如禅道,jenkins)的用户登录信息,并使用图标的形式动态显示,之前刚入门的时候接触过echarts 这 ...

  7. Mybatis通用Join的实现(最终版)

    你是否还在为mybatis的多表关联查询而写xml烦恼,是否还在为动态组装查询条件烦恼,是否还在为此没有合适的解决方案烦恼? mybatis-extension插件,解决开发过程中需要多表关联时需手写 ...

  8. android MVVM(2)用数据绑定关联VM 与 V

    1.官方文档 https://developer.android.com/topic/libraries/data-binding/architecture 2.简介 数据绑定库 可与MVVM 架构组 ...

  9. Linux常用命令--不断更新

    Linux命令: !. 1.[root@loc8lhost/root]# 表示登陆进去系统,其中#是超级⽤用户也即root⽤用 户的系统提示符 #. 2.reboot命令可以重启系统 $. 3.关闭系 ...

  10. 使用Vagrant 后发现虚拟机磁盘空间爆满的血泪填坑记

      现象:  用了几天vagrant后,发现docker 里的 Mysql5.7 服务无法启动,用docker ps 命令,发现mysql一直在反复重启, 查看mysql log 发现说磁盘空间不够, ...