当前位置: 首页 > news >正文

【JVM|垃圾回收】第二天

摘要:

        本文系统梳理了Java垃圾回收机制。首先介绍了两种回收判断方法:引用计数法(易产生循环引用)和可达分析法(通过根对象识别存活对象)。其次详细解析了五种引用类型:强引用、软引用、弱引用、虚引用和终结器引用。然后对比了三种回收算法:标记清除(速度快但碎片化)、标记整理(无碎片但慢)、复制法(快无碎片但耗内存)。最后概述了三种垃圾回收器:串行(适合小内存)、吞吐量优先(多核大内存)和响应时间优先(最小化单次停顿)。

一,回收判断

1,引用计数法

        当引用这个对象时,计数加一,无引用时计数为0。但是引出循环引用问题-->两个对象互相引用,这两个对象又没有被其他对象引用,因为技术不为0无法被回收。

2,可达分析法

通过指定不可回收的对象,包括-->roots根对象,直接或间接引用根对象的其他对象

根对象:1,system class对象(程序运行的基础)2,native class对象(访问操作系统的类)3,Thread对象(包括局部变量即栈帧)4,Busy Monitor对象

2.1,强引用

        root对象直接关联的对象,常见都为强引用,无强引用时会被回收。

2.2,软引用(new SoftReference(对象)数据不敏感且内存空间紧张时可使用)

        当没有强引用引用软引用对象时,垃圾回收后空间不足,会将软引用对象回收。

2.3,弱引用(new WeakReference(对象))

        当没有强引用引用弱引用对象时,无论内存充足与否都会回收掉弱引用对象,Full GC会清除所有弱引用。

补充:软弱引用也是一个对象,会占用一定内存,如果想要释放其内存,需要在引用队列找到这些对象然后回收。

2.4,虚引用

        例如Cleaner对象就是虚引用对象,引用byteBuffer,当byteBuffer被回收时,CLeaner对象会被放入引用队列,后台的一个守护线程就从队列中拿到虚引用对象然后调用clear等方法清除额外的内存:直接内存

2.5,终结器引用

        对象重写finallize()方法,jvm会为该对象创建一个终结器引用,当发生垃圾回收且没有强引用引用该对象时,该对象先不会被回收,而是终结器对象会被放入引用队列,该队列由一个优先级较低的线程管理,当线程执行接收到终结器引用就会根据该引用找到对应的对象,并执行finallize()方法然后下一次执行垃圾回收时进行回收

二,垃圾回收算法

1,标记清除

(1)标记

        根据可达分析法,找到没有被根对象引用的垃圾对象,对这些对象进行标记

(2)清除

        针对被标记的对象,通过将对象内存空间的启始位置记录的方式将该垃圾对象清除,后续其他对象创建时会直接从记录中寻找合适的空间放置。

优缺点:这种方法速度快,但是会造成内存碎片化

2,标记整理

        相较于标记清除,该方法在清除后多了一步整理的工作,将非垃圾对象规整使之变得紧凑,避免内存碎片化

缺点:因为整理内存,会额外消耗许多资源,因此会导致速度较慢

3,复制法

        该算法需要额外一块空间(from/to),当标记完成后就将from中存活的对象复制到To空间中,这个过程中自然就能够做到整理,最后交换from和To的引用(from<-->To)

优缺点:速度较快且不会由内存碎片化问题,但是要消耗额外内存空间

4,分代回收(堆空间划分为新生代和老年代)

补充:1,寿命阈值并非必定要求,如果新生代幸存区空间非常紧张,未达到寿命阈值的对象也会被放入老年代。 2,如果存入的是一个大对象(新生代清理后也一定放不下),不会触发垃圾回收而是直接被放入老年代中。

Tips:相关VM参数

三,垃圾回收器 

1,串行(回收期间阻塞用户线程)

(1)单线程

(2)堆内存小,适合个人电脑

2,吞吐量优先

(1)多线程

(2)堆内存大,多核CPU

(3)单位时间内,STW 的时间最短

Tips:执行效率和CPU核数密切相关,“所有线程”并行地进行垃圾回收,吞吐量大

3,响应时间优先(牺牲部分吞吐量并行执行换取响应时间)

(1)多线程

(2)堆内存大,多核CPU

(3)尽可能让单次 STW 的时间短

tips:CMS老年代的垃圾回收器如果失败-->退化到串行的垃圾回收,拖累响应时间

 

4,G1垃圾回收器(jdk9默认)

三个垃圾回收阶段

(1)Yong Collection新生代回收

(2)Yong Collection+CM

Tips:通过跨代引用老年代会被分为多个大小相等的区域放置对象,如果老年代中有root对象引用了新生代中的对象,这个区域会被标记为“脏卡”,该对象会记录root对象在老年代的引用地址,这样初始标记时就无需完全遍历老年代,而是直接扫描脏卡即可

(3)Mixed Collection混合收集

Tips:根据最大暂停时间有选择的进行老年代的垃圾回收,挑选那些回收价值较高的几个old区域----回收后能够释放的空间较多

 

http://www.dtcms.com/a/273190.html

相关文章:

  • Transformer模型原理概述
  • 【Linux】Linux 操作系统 - 27 , 进程间通信(三) --System V 共享内存
  • 零基础入门物联网-远程门禁开关:硬件介绍
  • 多线程学习
  • 指针的const应用
  • 老式MVC架构Web应用:经典框架下的技术坚守与现代挑战
  • STM32F103C8T6驱动无源蜂鸣器详解:从硬件设计到音乐播放
  • 使用SpringAOP自定义权限控制注解
  • 从零开始的语言模型构建 CS336 第一课(一)
  • 【Python练习】036. 编写一个函数,将一个字符串中的所有字符按ASCII值排序
  • 用OpenCV标定相机内参应用示例(C++和Python)
  • Git简单命令
  • 获取印度股票数据API实战指南:NSE与BSE双市场对接
  • 华为OD 周末爬山
  • upload-labs靶场通关详解:第21关 数组绕过
  • 微服务架构下的自动化测试策略调优经验分享
  • 【基于大模型 + FAISS 的本地知识库与智能 PPT 生成系统:从架构到实现】
  • Datawhale AI 夏令营:用户洞察挑战赛 Notebook(2)
  • HVV注意事项(个人总结 非技术)
  • 【HTTP服务端】Cookie?Session?Token?
  • React 自定义Hook——页面或元素滚动到底部监听 Hook
  • Java+Vue开发的资产设备全周期管理系统,移动端+后台管理,涵盖采购至报废全程,实现高效管理、成本可控与资源优化
  • Shell脚本一键部署KubeSphere前置环境
  • 04-ES6
  • 多线程 JAVA
  • Java :Optional容器类
  • python的保险业务管理与数据分析系统
  • AI 智能体:从辅助工具到自主决策者
  • 【YOLO脚本】对模型yaml文件测试
  • ZYNQ MPSOC PL端DDR4读写--仿真(3)