首页 > 编程语言 >Java的五大引用

Java的五大引用

时间:2022-11-13 21:36:40浏览次数:43  
标签:Java list System 回收 引用 new 五大 out

目录

五大引用概述

基于可达性算法的垃圾回收

image-20221113125807100

  • 实线是强引用,虚线是其他引用

强引用

image-20221113121216580

  • 只有所有 GC Roots 对象都不通过【强引用】引用该对象,该对象才能被垃圾回收
  • 我们平时用new出来的对象,用一个引用来指向这个对象,这个引用是强引用

软引用

image-20221113123644044

  • 通过GC Root对象强引用了我们的软引用对象,然后用软引用对象指向一个对象,这个对象就是被软引用指向的对象
  • 软引用自身也是会占内存的
  • 仅有软引用引用该对象时,在垃圾回收后,内存仍不足时会再次触发垃圾回收,回收软引用对象,可以配合引用队列来释放软引用自身

演示

/**
 * 演示软引用
 * -Xmx20m -XX:+PrintGCDetails -verbose:gc
 */
public class Demo2_3 {

    private static final int _4MB = 4 * 1024 * 1024;


	//这是我们的正常的进行创建对象,是强引用
    public static void main(String[] args) throws IOException {
        List<byte[]> list = new ArrayList<>();
        for (int i = 0; i < 5; i++) {
            list.add(new byte[_4MB]);
       }

        System.in.read();


    }
	//这是我们的软引用
    public static void soft() {
        // list --> SoftReference --> byte[]

        List<SoftReference<byte[]>> list = new ArrayList<>();
        for (int i = 0; i < 5; i++) {
            SoftReference<byte[]> ref = new SoftReference<>(new byte[_4MB]);
            System.out.println(ref.get());
            list.add(ref);
            System.out.println(list.size());

        }
        System.out.println("循环结束:" + list.size());
        for (SoftReference<byte[]> ref : list) {
            System.out.println(ref.get());
        }
    }
}

强引用执行的结果

image-20221113153150968

  • 会发生推内存溢出的现象,因为都是强引用,所以垃圾回收无法回收

软引用执行的结果

image-20221113153338607

  • 在第五次进行分配空间的时候,内存不够了,第一次进程垃圾回收发现内存还是不够,所以触发第二次的垃圾回收对软引用对象进行回收,所以发现前四个byte数组的内存地址为null

演示配合引用队列对软引用本身进行回收

import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;
import java.util.ArrayList;
import java.util.List;

/**
 * 演示软引用, 配合引用队列
 */
public class Demo2_4 {
    private static final int _4MB = 4 * 1024 * 1024;

    public static void main(String[] args) {
        List<SoftReference<byte[]>> list = new ArrayList<>();

        // 引用队列
        ReferenceQueue<byte[]> queue = new ReferenceQueue<>();

        for (int i = 0; i < 5; i++) {
            // 关联了引用队列, 当软引用所关联的 byte[]被回收时,软引用自己会加入到 queue 中去
            SoftReference<byte[]> ref = new SoftReference<>(new byte[_4MB], queue);
            System.out.println(ref.get());
            list.add(ref);
            System.out.println(list.size());
        }

        // 从队列中获取无用的 软引用对象,并移除
        Reference<? extends byte[]> poll = queue.poll();
        while( poll != null) {
            list.remove(poll);
            poll = queue.poll();
        }

        System.out.println("===========================");
        for (SoftReference<byte[]> reference : list) {
            System.out.println(reference.get());
        }

    }
}

  • queue队列就是我们的引用队列,当我软引用所关联的byte数组对象被回收,软引用就会加到queue中

弱引用

image-20221113124758706

  • 仅有弱引用引用该对象时,在垃圾回收时,无论内存是否充足,都会回收弱引用对象,可以配合引用队列来释放弱引用自身

演示

public class Code_09_WeakReferenceTest {

    public static void main(String[] args) {
//        method1();
        method2();
    }

    public static int _4MB = 4 * 1024 *1024;

    // 演示 弱引用
    public static void method1() {
        List<WeakReference<byte[]>> list = new ArrayList<>();
        for(int i = 0; i < 10; i++) {
            WeakReference<byte[]> weakReference = new WeakReference<>(new byte[_4MB]);
            list.add(weakReference);

            for(WeakReference<byte[]> wake : list) {
                System.out.print(wake.get() + ",");
            }
            System.out.println();
        }
    }

    // 演示 弱引用搭配 引用队列
    public static void method2() {
        List<WeakReference<byte[]>> list = new ArrayList<>();
        ReferenceQueue<byte[]> queue = new ReferenceQueue<>();

        for(int i = 0; i < 9; i++) {
            WeakReference<byte[]> weakReference = new WeakReference<>(new byte[_4MB], queue);
            list.add(weakReference);
            for(WeakReference<byte[]> wake : list) {
                System.out.print(wake.get() + ",");
            }
            System.out.println();
        }
        System.out.println("===========================================");
        Reference<? extends byte[]> poll = queue.poll();
        while (poll != null) {
            list.remove(poll);
            poll = queue.poll();
        }
        for(WeakReference<byte[]> wake : list) {
            System.out.print(wake.get() + ",");
        }
    }

}


弱引用执行的结果

image-20221113160053296

虚引用

虚引用有个最重要的应用就是我们的直接内存分配的ByteBuffer

image-20221113143059909

  • 必须配合引用队列使用,在上的ByteBuffer对象中的cleaner对象就是我们的虚引用,存储的是我们的直接内存的地址,然后我们的ReferenceHandler线程调用cleaner对象的clean方法,然后调用了unsafe.freeMemory来释放我们的直接内存

  • 因为直接内存不受JVM的内存自动管理的控制,所以通过这些方法来间接的实现对直接内存的回收

终结器引用

image-20221113145110661

  • finallize()方法是我们的Object中的方法,所以所有对象都有这个方法
  • 重写了了finalize方法,A4对象第一次垃圾回收的时候并不是立马被回收,因为重写了finallize方法,所以虚拟机会自动创建一个终结器引用,执行A4对象的第一次回收的时候,会将终结器引用放入引用队列(不会回收A4对象)
  • 由我们的Finalizer线程通过终结器引用找到被引用的对象,并调用他的finallize方法,第二次GC时才会回收这个A4对象
  • 不推荐使用
    • 因为处理引用队列的线程优先级很低,被处理的机会很少,可能造成这个对象的finallize()迟迟不被调用,导致这块内存迟迟不被回收

标签:Java,list,System,回收,引用,new,五大,out
From: https://www.cnblogs.com/lscCurry/p/16887018.html

相关文章

  • java——继承与多态——重点部分总结**********************************************
    Java类名必须是由一个或多个有意义的单词连缀而成的,每个单词首字母大写,其他字母全部小写,单词与单词之间不要使用任何分  成员变量名:成员变量名只要是一个合法的标识符......
  • Java索引
    Java运算符Java基础数据类型Java数组Java数组工具类--ArraysJava比较器--Compare/ComparableJava集合Java函数编程Java泛型编程......
  • pailler算法加密后如何进行密文计算-java
    1.背景工作中需要用到密文计算,涉及密文求和sum、平均avg以及加权平均wavg。特此分享,供参考。2.代码2.1分数类MyFraction涉及小数运算,但是密文目前只能存整数,所以考......
  • 【博学谷学习记录】超强总结,用心分享 。java基础知识。
    Java基础知识1.面向对象的特征封装:就是把对象的属性和行为结合为一个独立的整体,并尽可能隐藏对象的内部实现细节,就是把不想告诉或者不该告诉别人的东西......
  • Java比较器
    一、Comparable接口类直接实现Comparable接口,并实现compareTo方法packagecn.lxx.test;publicclassUserimplementsComparable<User>{//该类实现Comparable接......
  • Java 使用JavaMail通过Gmail发送电子邮件
    JavaMail提供给开发者处理电子邮件相关的编程接口。它是Sun发布的用来处理email的API可以方便地执行一些常用的邮件传输。可以基于JavaMail开发出类似于MicrosoftOutlook......
  • Java安全之Mojarra JSF反序列化
    Java安全之MojarraJSF反序列化AboutJSFJavaServerFaces,新一代的JavaWeb应用技术标准,吸收了很多JavaServlet以及其他的Web应用框架的特性。JSF为Web应用开发定义了一......
  • 学习Java前的快捷键和软件配置
    目标熟练掌握java每天编写一篇笔记java和python都要学习每天最少要学习4个视频电脑的快捷键ctrl+c复制ctrl+v粘贴ctrl+a全选ctrl+x剪切ctrl+z......
  • java集合
    Java集合分类数据结构一:集合框架的概述1.集合、数组都是对多个数据进行存储的结构简称java容器说明:此时的存储,主要还是内存层面的存储,不涉及持久化存储(数据库、硬......
  • Java数组工具类Arrays
    Arrays所在的包是Java.util.*,Arrays提供的全部是static方法。1.转字符串1.1一维数组--publicstaticStringtoString(int[]a)参数即可以是基础类型数组,也可以是包装......