JVM篇:垃圾回收

如何判断对象可以被回收

Java中对象能否被回收,是根据兑现是否被引用来决定的。如果对象被引用了,说明该对象还在使用,不允许被回收

main栈帧中demo变量存储着Demo实例对象的地址,与Demo实例对象建立了连接关系此时Demo实例对象可以通过demo访问,因此这个对象不能被回收。

当demo为null时,与Demo实例对象不存在连接关系,此时Demo对象就可以被回收了

引用计数法

引用计数是计算机编程语言中的一种内存管理技术,是指将资源(可以是对象、内存或磁盘空间等等)的被引用次数保存起来,当被引用次数变为零时就将其释放的过程。使用引用计数技术可以实现自动资源管理的目的。同时引用计数还可以指使用引用计数技术回收未使用资源的垃圾回收算法。需要注意的是,Java从来没有使用过该方法去实现GC。

一个对象被引用时计数器就进行+1,被引用次数减少一次时就-1。

public class demo8 {
    public static void main(String[] args) {
        String s1 = new String();  //s1的计数器加一
        String s2 = new String();  //s2的计数器加一
        s1 = s2;  //s2的计数器加一
        s1 = null;  //s1的计数器减一,此时为0,满足被释放条件。s2计数器减一,此时为1。
    }
}

优点

即时性:当引用变为零时会被直接回收。

无需遍历堆可以准确释放对应内存。

缺点

计数器开销大,每个对象都需要一个计数器,计数器的存储开销比较大,计数器增减时时间开销大

循环引用时无法做到垃圾回收

class A {
    B b;

    public A(B b) {
        this.b = b;
    }
}

class B {
    A a;

    public B(A a) {
        this.a = a;
    }
}

public class Main {
    public static void main(String[] args) {
        A a = new A(new B(null));//创建A对象引用,计数器加1
        B b = new B(a);//被对象b的属性a引用,计数器再加1
        a.b = b;
        a = null;//a不引用A了,计数器减1,但还被b.a引用。因此无法被回收。
        b = null;
    }
}

可达性分析算法

也可以称为根搜索算法、追踪性垃圾收集。所谓可达性分析就是,在垃圾回收之前,对堆中所有的对象进行扫描,看是否被根对象(一定不会被回收的对象)直接或间接引用,如果是则无法被回收,没有被引用则可回收。

GC Root对象是哪些?

  • 加入了synchronized同步锁的对象可以被当作GC Root
  • 本地方法栈内的引用的对象
  • 虚拟机栈中所引用的对象。如各个线程被调用的方法中使用到的参数、局部变量等。
  • 方法区中常量引用的对象。如String Table中里的引用的。
  • 基本数据类型对应的 Class 对象

简单讲,凡是被常量、静态变量、全局变量、运行时方法中的变量直接引用的对象,原则上不能被GC释放。

四种引用

强引用:上图中的实线,对于强引用对象,JVM何时都不会对其进行回收,即使是出现OOM错误(因此内存泄漏主要原因就是强引用对象无法被回收)。但是当强引用对象超过了作用域(暂时不理解)又或是显式将强引用赋值null(也就是解除了强引用关系)则可以被回收。

软引用SoftReference:对于弱引用对象,进行一次GC回收后,内存还是不足时会对其进行回收,否则可以保持存活。(可以用来实现缓存)

弱引用WeakReference:在执行GC回收时,内存即使充足也会被回收

虚引用PhantomReference:并不会决定对象的生命周期,虚引用并不能单独使用,而是要和引用队列一起使用,也不能通过虚引用来获取引用的对象。在JDK8版本中,当GC准备回收一个虚引用指向的对象时,会将虚引用存入引用队列,而被指向的对象不会被真正的回收。由另一线程去读取引用队列中的引用来执行被引用的对象回收之前的内存释放操作。例如Clearner类就是虚引用,在ByteBuffer类对象被回收之前,先进行直接内存的释放(释放操作在Clearner类中实现)再进行回收对象。但在JDK9之后虚引用不会对对象的生存产生任何影响。

需要注意的是,上图中的软引用与弱引用实际上也是一个对象,当引用的对象回收时,这些引用对象并不会被回收(因为被GC Root强引用),而是会被放入一个引用队列当中,当内存不足时,会通过遍历引用队列将这些已经没有引用对象的引用释放。

除了以上四种引用,还存在一种终结器引用,当GC回收一个重写了finalize()方法的对象时,JVM会给被回收对象创建一个终结器引用,同时将该引用放入引用队列,通过一个FinalizerHandler线程去处理引用队列当中的终结器引用,首先是判断被回收对象是否执行了finalize()方法,如果没有则执行,等到下一次GC时才会去释放该对象。

//-Xmx20m
public class demo9 {
    private final static int _4M = 4 * 1024 * 1024;

    public static void main(String[] args) {
        List<SoftReference<byte[]>> list = new ArrayList();
    	//list -->SoftReferencr -->byte
        for (int i = 0; i < 5; i++) {
            SoftReference<byte[]> softReference = new SoftReference<>(new byte[_4M]);
            System.out.println(softReference.get());
            list.add(softReference);
            System.out.println(list.size());
        }
        for (SoftReference<byte[]> softReference : list) {
            System.out.println(softReference.get());
        }
    }
}

运行结果如下

[B@1540e19d
1
[B@677327b6
2
[B@14ae5a5
3
[B@7f31245a
4
[B@6d6f6e28
5
null
null
null
null
[B@6d6f6e28

指定堆内存为20M,然后进行创建5次字节对象,将会进行内存回收,由运行结果可以看出来,前四次的软引用对象已经被释放,只留下了最后一个软引用对象。

可以看出在进行第二次垃圾回收时,连续回收了两次,因为第一次回收并没有回收充足的内存,因此执行第二次垃圾回收将软引用回收。

但是我们并不需要已经被回收的软引用,仍存在list队列中占用内存空间。我们可以将软引用关联到引用队列。

public class demo9 {
    private final static int _4M = 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++) {
            //指定绑定队列,只有软引用对象被回收的话,才会被加入引用队列
            SoftReference<byte[]> softReference = new SoftReference<>(new byte[_4M], queue);
            System.out.println(softReference.get());
            list.add(softReference);
            System.out.println(list.size());
        }

        Reference<? extends byte[]> poll = queue.poll();
        while (poll != null) {
            list.remove(poll);
            poll = queue.poll();
        }

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

运行结果

可以看到软引用对象被回收的软引用也被释放

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/351644.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

2024新版68套Axure RP大数据可视化大屏模板及通用组件+PSD源文件

Axure RP数据可视化大屏模板及通用组件库2024新版重新制作了这套新的数据可视化大屏模板及通用组件库V2版。新版本相比于V1版内容更加丰富和全面&#xff0c;但依然秉承“敏捷易用”的制作理念&#xff0c;这套作品也同样延续着我们对细节的完美追求&#xff0c;整个设计制作过…

关于binlog文件恢复数据库的方法

今天给大家讲解下&#xff0c;binlog日志恢复数据库的方法&#xff0c;之前由于数据库中了勒索病毒&#xff0c;这期文章告诉你恢复的方法&#xff1a;下面这种千万不要支付&#xff0c;支付了也不会给恢复 找到binlog文件&#xff1a; 这里我只恢复00032和00033即可&#xff1…

鸿蒙开发初体验

文章目录 前言一、环境配置1.1 安装DevEco Studio1.2 安装相关环境 二、工程创建三、工程结构介绍四、代码实现4.1 初识ArkTs4.2 具体实现 参考资料 前言 HarmonyOS是华为公司推出的一种操作系统&#xff0c;旨在为不同设备提供统一的操作系统和开发平台。鸿蒙开发的出现为用户…

【深度学习】sdxl中的 text_encoder text_encoder_2 区别

镜像问题是&#xff1a;https://editor.csdn.net/md/?articleId135867689 代码仓库&#xff1a; https://huggingface.co/stabilityai/stable-diffusion-xl-base-1.0/tree/main 截图&#xff1a; 为什么有两个CLIP编码器 text_encoder 和 text_encoder_2 &#xff1f; 在…

照片怎么弄成jpg格式文件?jpg图片格式转换器介绍

jpg图片格式作为最常用的图片格式类型之一&#xff0c;不管是平时下载还是拍摄的照片大多数都属于jpg格式&#xff0c;还有我们在制作证件照照片时&#xff0c;通常需要将照片转换成jpg格式&#xff0c;以便更好地保存、打印或上传至网站等&#xff0c;那么图片转换为jpg需要怎…

day31_HTML

今日内容 0 复习昨日 1 表格标签 2 表单标签【重要】 3 框架标签 0 复习昨日 Javaweb开发,前端,服务器,数据库 前端,要学习HTML,CSS,JavaScript,JQuery HTML是用来编写网页的一种编程语言 语法 由各种标签组成,标签是尖括号<>,一般都是成对儿出现,前面叫做开标签,后面…

SpringBoot自定义全局异常处理器

文章目录 一、介绍二、实现1. 定义全局异常处理器2. 自定义异常类 三、使用四、疑问 一、介绍 Springboot框架提供两个注解帮助我们十分方便实现全局异常处理器以及自定义异常。 ControllerAdvice 或 RestControllerAdvice&#xff08;推荐&#xff09;ExceptionHandler 二、…

学习gin框架知识的注意点

这几天重新学习了一遍gin框架&#xff1a;收获颇多 Gin框架的初始化 有些项目中 初始化gin框架写的是&#xff1a; r : gin.New() r.Use(logger.GinLogger(), logger.GinRecovery(true)) 而不是r : gin.Default() 为什么呢&#xff1f; 点击进入Default源码发现其实他也是…

如何在有或没有备份的 iPhone 上检索已删除的短信

iPhone 清理垃圾短信时不小心删除了一些重要短信&#xff1f;想知道如何找回 iPhone 上已删除的短信吗&#xff1f;如果您已将设备备份到 iCloud 或 iTunes&#xff0c;则可以从备份恢复 iPhone 上的短信。如果没有备份&#xff0c;您可以尝试第三方iPhone短信恢复程序来恢复它…

记一个信息泄露到RCE

打点 开局一个登录框 信息收集 发现了一处接口泄露了部分信息 不过只有支付宝密钥的信息无法扩大危害&#xff0c;此时尝试寻找了一下其他同类型系统同样的接口&#xff0c;查看一下是否泄露的信息相同 因为如果相同就说明是静态的&#xff0c;没有价值横向收集 此时访问其他…

RabbitMQ概念

一 、RabbitMQ概念 1 架构图 2 相关概念 Publisher - ⽣产者&#xff1a;发布消息到RabbitMQ中的Exchange Consumer - 消费者&#xff1a;监听RabbitMQ中的Queue中的消息 Broker&#xff1a;接收和分发消息的应用&#xff0c;RabbitMQ Server就是 Message Broker&#xf…

力扣日记1.27-【回溯算法篇】131. 分割回文串

力扣日记&#xff1a;【回溯算法篇】131. 分割回文串 日期&#xff1a;2023.1.27 参考&#xff1a;代码随想录、力扣 131. 分割回文串 题目描述 难度&#xff1a;中等 给你一个字符串 s&#xff0c;请你将 s 分割成一些子串&#xff0c;使每个子串都是 回文串 。返回 s 所有可…

Android App开发-简单控件(2)——视图基础

2.2 视图基础 本节介绍视图的几种基本概念及其用法&#xff0c;包括如何设置视图的宽度和高度&#xff0c;如何设置视图的外部间距和内部间距&#xff0c;如何设置视图的外部对齐方式和内部对齐方式等等。 2.2.1 设置视图的宽高 手机屏幕是块长方形区域&#xff0c;较短的那…

Unknown encoder ‘libmp3lame

环境&#xff1a; macos m1 &#xff0c; python3.10.x 背景 做视频切片&#xff0c; 使用moviepy 中VideoFileClip进行截取视频。 报错&#xff1a; Unknown encoder libmp3lameThe audio export failed because FFMPEG didnt find the specified codec for audio encoding …

ppt背景图片怎么设置?让你的演示更加出彩!

PowerPoint是一款广泛应用于演示文稿制作的软件&#xff0c;而背景图片是演示文稿中不可或缺的一部分。一个好的背景图片能够提升演示文稿的整体效果&#xff0c;使观众更加关注你的演示内容。可是ppt背景图片怎么设置呢&#xff1f;本文将介绍ppt背景图片设置的三个方法&#…

浪花 - 添加队伍业务开发

一、接口设计 1. 请求参数&#xff1a;封装添加队伍参数 TeamAddRequest package com.example.usercenter.model.request;import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.ann…

STM32 freertos 使用软件模拟串口uart

如题&#xff0c;为什么要这样做&#xff1f; 最近做的一个项目上使用了74HC595作为指示灯板使用&#xff1b; 这个灯板与驱动板是通过排线连接&#xff0c;排线约25cm长&#xff1b; 在实验室测试一切正常&#xff0c;发到客户手上使用就出现了某个LED跳动情况&#xff1b;…

Spring Boot 中 Service 层依赖注入问题

目录 问题描述 产生错误 问题原因 解决方法 手动注入方法 1、使用工具集 hutool&#xff0c;引入 Maven 依赖 2、编写 SpringUtil 工具类 问题描述 Controller 层方法为 static 静态&#xff0c;引入 Service 层时使用 Autowired 注解自动装配&#xff0c;Controller层方…

2017年认证杯SPSSPRO杯数学建模D题(第二阶段)教室的合理设计全过程文档及程序

2017年认证杯SPSSPRO杯数学建模 D题 教室的合理设计 原题再现&#xff1a; 某培训机构租用了一块如图&#xff08;见附件&#xff09;所示的场地&#xff0c;由于该机构开设了多种门类的课程&#xff0c;所以需要将这块场地通过加入一些隔墙来分割为多个独立的教室和活动区。…

手把手教学:AD09制作BOM及小技巧

BOM&#xff08;Bill of Material&#xff09;物料清单&#xff0c;是以数据格式来描述产品结构的文件&#xff0c;即生产一件产品所需的子零件及其产品中零件数量的完全组合。这里生成BOM表用作对你制作的pcb板进行成本预估和制作生产资料文件。同时也是样品制作时&#xff0c…