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对象引用,计数器加1B b = new B(a);//被对象b的属性a引用,计数器再加1a.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 -->bytefor (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());}}
}

运行结果

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

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

wsl下安装ros2问题: Unable to locate package ros-humble-desktop 解决方案

❗ 问题 在wsl&#xff08;Ubuntu 22.04版本&#xff09;下安装ros的过程中&#xff0c;在执行命令 $ sudo apt install ros-humble-desktop一直弹出报错&#xff1a;Unable to locate package ros-humble-desktop 前面设置编码和添加源的过程中一直没有出现其他问题&#…

游泳耳机入耳式好,还是骨传导好?游泳听音乐最好的耳机推荐

在游泳馆或海边&#xff0c;热爱游泳的人们在水中尽情畅游&#xff0c;享受着清凉的水流和游动的乐趣。为了让游泳体验更上一层楼&#xff0c;戴上专为游泳设计的耳机成为不可或缺的一环。游泳耳机不仅防水&#xff0c;还能让你在畅游的同时&#xff0c;尽情享受高质量的音乐&a…

Android Studio离线开发环境搭建

Android Studio离线开发环境搭建 1.下载离线和解压包2.创建工程3.创建虚拟机tips 1.下载离线和解压包 下载地址 百度网盘&#xff1a;https://pan.baidu.com/s/1XBPESFOB79EMBqOhFTX7eQ?pwdx2ek 天翼网盘&#xff1a;https://cloud.189.cn/web/share?code6BJZf2uUFJ3a&#…

VMware虚拟机部署Linux Ubuntu系统

本文介绍基于VMware Workstation Pro虚拟机软件&#xff0c;配置Linux Ubuntu操作系统环境的方法。 首先&#xff0c;我们需要进行VMware Workstation Pro虚拟机软件的下载与安装。需要注意的是&#xff0c;VMware Workstation Pro软件是一个收费软件&#xff0c;而互联网中有很…

[GYCTF2020]Ezsqli1

打开环境&#xff0c;下面有个提交表单 提交1&#xff0c;2有正确的查询结果&#xff0c;3以后都显示Error Occured When Fetch Result. 题目是sql&#xff0c;应该考察的是sql注入 简单fuzz一下 发现information_schema被过滤了&#xff0c;猜测是盲注了。 测试发现只要有东…

OSI七层模型 | TCP/IP模型 | 网络和操作系统的联系 | 网络通信的宏观流程

文章目录 1.OSI七层模型2.TCP/IP五层(或四层)模型3.网络通信的宏观流程3.1.同网段通信3.2.跨网段通信 1.OSI七层模型 在计算机通信诞生之初&#xff0c;不同的厂商都生产自己的设备&#xff0c;都有自己的网络通讯标准&#xff0c;导致了不同厂家之间各种协议不兼容&#xff0…

(大众金融)SQL server面试题(1)-总销售量最少的3个型号的车及其总销售量

今天&#xff0c;面试了一家公司&#xff0c;什么也不说先来三道面试题做做&#xff0c;第一题。 那么&#xff0c;我们就开始做题吧&#xff0c;谁叫我们是打工人呢。 题目是这样的&#xff1a; 统计除豪车外&#xff0c;销售最差的车 车辆按批销售&#xff0c;每次销售若干…

通俗易懂理解MobileNet网络模型

温故而知新&#xff0c;可以为师矣&#xff01; 一、参考资料 详细且通俗讲解轻量级神经网络——MobileNets【V1、V2、V3】 MobileNet v1 和 MobileNet v2 二、MobileNet v1 原始论文&#xff1a;[1] MobileNet网络详解 【深度学习】轻量化CNN网络MobileNet系列详解 Mo…

RLHF学习

整体流程 三个步骤分解&#xff1a; 预训练一个语言模型 (LM) &#xff1b;聚合问答数据并训练一个奖励模型 (Reward Model&#xff0c;RM) &#xff1b;用强化学习 (RL) 方式微调 LM。 RW RM 的训练是 RLHF 区别于旧范式的开端。这一模型接收一系列文本并返回一个标量奖励&…

力扣hot100 最小栈 变种栈

Problem: 155. 最小栈 文章目录 思路&#x1f496; Stack 自定义 Node&#x1f37b; Code 思路 &#x1f469;‍&#x1f3eb; 甜姨 &#x1f496; Stack 自定义 Node 时间复杂度: O ( 1 ) O(1) O(1) 空间复杂度: O ( n ) O(n) O(n) &#x1f37b; Code class MinS…

轻松打卡:使用Spring Boot和Redis Bitmap构建高效签到系统【redis实战 四】

欢迎来到我的博客&#xff0c;代码的世界里&#xff0c;每一行都是一个故事 轻松打卡&#xff1a;使用Spring Boot和Redis Bitmap构建高效签到系统【redis实战 四】 引言(redis实战)前言回顾bitmap基本概念核心特性使用场景 为什么使用redis中的bitmap实现&#xff1f;1. 存储效…

紫光展锐M6780丨超分辨率技术——画质重构还原经典

上一期&#xff0c;我们揭秘了让画质更加炫彩的AI-PQ技术。面对分辨率较低的老电影&#xff0c;光有高饱和度的色彩是不够的&#xff0c;如何能够提高视频影像的分辨率&#xff0c;使画质更加清晰&#xff0c;实现老片新看&#xff1f; 本期带大家揭晓紫光展锐首颗AI8K超高清智…

【分布式技术专题】「分布式技术架构」 探索Tomcat技术架构设计模式的奥秘(Server和Service组件原理分析)

探索Tomcat技术架构设计模式的奥秘 Tomcat系统架构分析Tomcat 整体结构Tomcat总体结构图以 Service 作为“婚姻”1) Service 接口方法列表 2) StandardService 的类结构图方法列表 3) StandardService. SetContainer4) StandardService. addConnector 以 Server 为“居”1) Ser…

etcd技术解析:构建高可用分布式系统的利器

1. 引言 随着云原生技术的兴起&#xff0c;分布式系统的构建变得愈发重要。etcd作为一个高可用的分布式键值存储系统&#xff0c;在这个领域发挥着至关重要的作用。本文将深入探讨etcd的技术细节&#xff0c;以及如何利用它构建高可用的分布式系统。 2. etcd简介 etcd是一个开…

JVM系列-9.性能调优

&#x1f44f;作者简介&#xff1a;大家好&#xff0c;我是爱吃芝士的土豆倪&#xff0c;24届校招生Java选手&#xff0c;很高兴认识大家&#x1f4d5;系列专栏&#xff1a;Spring原理、JUC原理、Kafka原理、分布式技术原理、数据库技术、JVM原理&#x1f525;如果感觉博主的文…

大数据安全 | 期末复习(中)

文章目录 &#x1f4da;感知数据安全⭐️&#x1f407;传感器概述&#x1f407;传感器的静态特性&#x1f407;调制方式&#x1f407;换能攻击&#x1f407;现有防护策略 &#x1f4da;AI安全⭐️&#x1f407;智能语音系统——脆弱性&#x1f407;攻击手段&#x1f407;AI的两…

探索IOC和DI:解密Spring框架中的依赖注入魔法

IOC与DI的详细解析 IOC详解1 bean的声明2 组件扫描 DI详解 IOC详解 1 bean的声明 IOC控制反转&#xff0c;就是将对象的控制权交给Spring的IOC容器&#xff0c;由IOC容器创建及管理对象。IOC容器创建的对象称为bean对象。 要把某个对象交给IOC容器管理&#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; 在…

那些年与指针的爱恨情仇(一)---- 指针本质及其相关性质用法

关注小庄 顿顿解馋 (≧∇≦) 引言&#xff1a; 小伙伴们在学习c语言过程中是否因为指针而困扰&#xff0c;指针简直就像是小说女主&#xff0c;它逃咱追&#xff0c;我们插翅难飞…本篇文章让博主为你打理打理指针这个傲娇鬼吧~ 本节我们将认识到指针本质&#xff0c;何为指针和…

RHCE项目:使用LNMP搭建私有云存储

目录 一、准备工作 1、关闭防火墙、安全软件 2、搭建LNMP环境 3、上传软件 4、设置nextcloud安装命令权限 二、数据库 1、设置数据库 2、重启数据库 三、配置nginx 四、安装nextcloud 五、内网穿透 1、创建内网映射 2、linux系统安装花生壳客户端 3、重新打开浏览…