漫画:什么是 JVM 的垃圾回收?_CSDN 程序人生的博客-程序员秘密

技术标签: jvm  junit  java  编程语言  oom  

作者 | 鸫鸫鹅,小灰

来源 | 程序员小灰(ID:chengxuyuanxiaohui)


—————  第二天  —————


————————————


下面我们一起来研究这三个问题。

问题1:哪些是需要回收的?

首先我们需要知道如何哪些垃圾需要回收?判断对象是否需要回收有两种算法。一种是引用计数算法、一种是可达性分析算法。

引用计数算法

引用计数算法很简单,它通过记录对象被引用的次数从而判断该对象的重要程度。如果该对象被其它对象引用,则它的引用计数加一,如果删除对该对象的引用,那么它的引用计数就减一,当该对象的引用计数为0时,那么该对象就会被回收。

引用计数存在什么问题呢?当有两个对象相互引用时,由于它们互相引用对方所以计数都不为零,这就会导致这两个对象无法回收。

所以,Java虚拟机采用的是另一种方法来判断对象是否存活,它就是可达性分析算法。

可达性分析算法

可达性分析算法,首先要确定一系列根对象(GC Roots),并从根对象为起点根据对象之间的引用关系搜索出一条引用链(Reference Chain),在引用链的对象就存活,而不在引用链的对象就认定为可回收对象。

有一个比喻十分恰当:可达性分析算法就好比是在清洗葡萄串,我们可以从一根枝提起一大串葡萄,他们就像一串引用链,而没有和引用链相连的对象就像是散落在池子里的葡萄,可以回收。


  • 虚拟机栈中引用的对象(正在运行的方法使用到的变量、参数等)

  • 方法区中类静态属性引用的对象(static关键字声明的字段)

  • 方法区中常量引用的对象,(也就是final关键字声明的字段)

  • 本地方法栈中引用的对象(native方法)

  • Java虚拟机内部的引用。(系统内部的东西当然能作为根了)

问题2:有哪些重要的垃圾回收算法?

学会判断内存中哪些垃圾需要回收后,我们就需要掌握几个重要的垃圾回收算法。

标记-清除算法

标记-清除法是最基本的一种垃圾回收算法,总的来说分为两步:

  • 标记

标记所有需要回收的对象(灰色),也就是在做垃圾的判定。

  • 清除

将标记为灰色的部分,清除掉。

需要注意的是:所谓的清除,并不需要真正地把整个内存的字节进行清零操作,只需要把空闲对象的起始结束地址记录下来放入空闲列表里,表示这段内存是空闲的就行。

  • 优点速度快,只需要做个标记就能知道哪一块需要被回收,但是他的缺点也是致命的。

  • 他的主要缺点有两个:一是执行效率不稳定,二是会涉及到内存碎片化的问题。

可能有人会问,碎片化是什么意思呢?上面所描述的这个栈,通过标记清除法虽然是清除了空间,但是清除出来的内存是大量的不连续内存碎片,像下面的这块对象,明明整体都有位,却因为不连续无法放入,这是标记-清除算法最大的缺点。

所谓标记复制算法和标记整理算法,都是对标记清除算法缺点的改进,所以才说标记清除算法是最基础的方式。

标记-整理算法

与标记-清除算法不同,标记-整理算法是移动式的。他会让所以存活的对象都向内存空间一端移动,然后清除到边界以外的内存。

  • 标记

  • 移动

是什么样的弊端呢?标记-整理算法涉及到了对象的移动,在整理阶段,由于移动了可用对象,需要去更新引用。效率就低了。

标记-复制算法

标记-复制算法,相比前面的比较不同,他将内存空间分为两块,在垃圾回收时将正在使用的内存中的存活对象复制到未被使用的内存块中,然后呢再清除正在使用的内存块中的所有对象。最后再交换两个内存的角色,最后完成垃圾回收。

大体来看可以分为 这么几个步骤:

  • 复制

  • 清空

  • 易位

不难看出,标记复制算法不需要标记算是提升了效率。此外他也不会参数碎片问题。

但是。标记复制算法的缺点也是十分明显的,它需要双倍空间。

问题3:垃圾回收的具体流程是怎样的?

既然说JVM虚拟机不会单独采用某种算法,而是会结合三种算法让他们协同工作,其具体的实现就是java虚拟机里的分代垃圾回收机制。

上图所示,就是Java堆内存的划分。为什么需要这么划分区域呢?那是因为我们的java对象寿命都是不同的,有的可能需要长时间使用,而有的可能用完就可以丢去。于是我们可以根据其生命周期的不同特点,进行不同的垃圾回收策略。

总的来说,新生代的垃圾回收比较频繁,老年代很久才触发一次垃圾回收。新生代处理的都是一些朝生夕死的对象,而老年代回收的是更有价值的,会长时间存活的对象。

举个很好理解的例子:新生代处理垃圾,就像是处理生活日用垃圾,而老年代处理的垃圾,更像是过年大扫除,家里实在太多垃圾了来一次重清理。大扫除清理的垃圾,都是在家中存放时间较长的,往往可能曾经很受用,如今退役了先放着过年再打扫清除掉。

每一次,我们创建一个对象,都会在伊甸园区占据一定内存大小,渐渐地伊甸园就满了。当我们再要创建对象时,就会发现空间不够了。

这时,就会触发一次垃圾回收,新生代触发的垃圾回收有个称呼叫做MinorGC。

MinorGC触发后,伊甸园区就会对各个对象进行可达性分析,从而知道哪些对象应该作为垃圾被清理。

MinorGC在这里采取的是标记复制算法,它将有用的对象存放到幸存区to,然后把伊甸园中的对象清除掉。

进入幸存区的幸运儿,将会被标记上一个“幸运值”,代表他们抗住了多少次清理。

最后,幸存区to和幸存区from还需要交互一下位置,这里不是指物理位置交换,而是说,它俩的定义发生了交换,下次就是左边那个为幸存区to,右边的为幸存区from了。

换句话说,幸存区to始终是空的。

我们再模拟多几次,加深一下印象:

假如又进来了不少对象,伊甸园又满了!

那就会触发一次MinorGC,把幸存者移步到幸存区to,其他一律清空。

最后别忘了,幸存区from和幸存区to又要再交换一下”位置“。

...


☞“搏一搏,单车变摩托!”华为天才少年耗时四个月,将自行车强势升级为自动驾驶
☞粽子也内卷?2021 互联网大厂端午礼盒大盘点
☞百年通信史:落后西方半世纪的中国,用 20 年绝地反杀!| 文末送福利
☞Windows 10 还有前途么?
☞苹果又魔改安卓?iOS 15 正式发布、可跨设备移动文件,这届 WWDC21 带来了什么?

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/csdnsevenn/article/details/117935804

智能推荐

# Cobalt Strike:使用已知的私钥解密流量-Part 1_爱你'非我莫属。的博客-程序员秘密

博客系列:Cobalt Strike:流量解密Cobalt Strike:使用已知的私钥解密流量-Part 1(当前部分)Cobalt Strike: 使用已知的私钥解密流量 - Part 2Cobalt Strike: 使用进程内存解密流量 - Part 3Cobalt Steike: 解密被掩盖的流量 - Part 4Cobalt Strike: 解密DNS流量 - Part 5我们发现6个流氓软件Cobalt Strike的私钥,可以用来将C2网络流量进行解密Co

数据结构排序-------插入排序(C,Java实现)_楠哥学IT的博客-程序员秘密

 1、插入排序简要概述  它的基本思想是:把n个待排序的元素看成为一个有序表和一个无序表,开始时有序表中只包含一个元素,无序表中包含有n-1个元素,排序过程中每次从无序表中取出第一个元素,把它的排序码依次与有序表元素的排序码进行比较,将它插入到有序表中的适当位置,使之成为新的有序表。 2、插入排序图解  3、代码实现public class test { public static void main(String[] args) { int array[] = new

NFS共享存储服务安装_huryer的博客-程序员秘密_安装nfs网络共享服务的步骤

NFS是一种基于TCP/IP 传输的网络文件系统协议。通过使用NFS协议,客户机可以像访问本地目录一样访问远程服务器中的共享资源NAS存储: NFS服务的实现依赖于RPC (Remote Process Call,远端过程调用)机制,以完成远程到本地的映射过程。在Centos 7系统中,需要安装nfs-utils、 rpcbind 软件包来提供NFS共享服务,前者用于NFS共享发布和访问,后者用于RPC支持。手动加载NFS共享服务时,应该先启动rpcbind, 再启动nfs。nfs端口:2049R

android开发环境的搭建!浅谈Android消息机制原理,重难点整理_普通网友的博客-程序员秘密

开头技术的发展产生了程序员这个职位,从这些年各大互联网公司曝光的一些员工收入水平来看,程序员的工资还是相对比较高的,可是我们在互联网上还听到了另外一种声音,很多程序员想转行,特别是大龄程序员,这可能会令很多人纳闷。为什么工资这么高还想转行呢?其实他们也很无奈,从下面几点可以看得出来。Android高级知识点一、Android性能优化1.描述一下android的系统架构?2.Android线程间通信有哪几种方式3. 如何避免OOM异常4.Android程序运行时权限与文件系统权限的区别?5.H

HCIA学习笔记#4_沙漏hx的博客-程序员秘密

第四天补充遗漏的点:暂无路由

IOS 获取系统时间戳_dianli0581的博客-程序员秘密

IOS 获取系统时间戳常用方法通用方法有如下三种: NSLog(@"1 ========== %.0lf",(double)time(NULL)*1000); NSDate* dat = [NSDate dateWithTimeIntervalSinceNow:0]; NSTimeInterval a=[dat timeInterv...

随便推点

【特征检测】Harris角点检测中的数学推导_lbaihao的博客-程序员秘密

简介本文主要是对Harris角点检测的数学公式进行推导,更加深入的掌握原理性的理论知识。预备知识椭圆的矩阵方程表示在高中课本中,我们学习到标准椭圆及其方程(如下图所示):其实,矩阵在运算中使用非常广泛,现将上述标准方程写成矩阵形式(方便接下来的处理):椭圆半轴与系数矩阵的关系         一个nxn的矩阵,

ROM测试工程师岗位考核标准_三千红尘客的博客-程序员秘密_测试工程师试用期考核标准

1.出勤率及工工作时长 (测试部评审委员会评分)不迟到不早退(出勤一天满9小时)自主适当加班完成任务加班时间用于提升自我,输出有效文档2.任务完成情况(1)任务量(组长)每月正常完成分配的任务每月平均每日相当于1.2人工作分量每月平均每日相当于1.5人工作分量(2)用例执行质量(测试部评审委员会评分)用例规范执行,非PASS项需要清晰备注用例不规范处有建议用例执行完成无空白,专项有报告,有标注主动...

MapReduce中使用字符串拼接导致的问题_快乐程序员的博客-程序员秘密_reduce字符串拼接

今天在帮业务方优化mapreduce作业时遇到一个用字符串拼接的问题。

SQL删除某个时间段的数据_weixin_30802273的博客-程序员秘密

DELETE from dbcp_log_read where time BETWEEN '2017-02-20 00:00:00' AND '2017-03-06 00:00:00'转载于:https://www.cnblogs.com/ouyanxia/p/6510781.html

Java 中如何使用动态数组_开开心心 everyday的博客-程序员秘密

新建 ArrayList对象 ,然后使用add即可例如:ArrayList list = new ArrayList(); for( int i=0;i <10;i++ ) list.Add(i); 参考: https://www.cnblogs.com/qingchunshiguang/p/6103731.html...

vscode 小程序wxml文件代码没有颜色区分(高亮)解决办法_前端步锦的博客-程序员秘密_vscode wxml高亮

打开编辑器wxml文件,右下角,点击如下图部分:在上面的弹框中选择“HTML”语言模式:就可以正常显示了PS:其他语言模式也可以任意切换,就看自己需要什么格式了~...

推荐文章

热门文章

相关标签