JVM(2)--一文读懂垃圾回收

与其他语言相比,例如c/c++,我们都知道,java虚拟机对于程序中产生的垃圾,虚拟机是会自动帮我们进行清除管理的,而像c/c++这些语言平台则需要程序员自己手动对内存进行释放。

虽然这种自动帮我们回收垃圾的策略少了一定的灵活性,但却让代码编写者省去了很多工作,同时也提高了很多安全性。(因为像C/C++假如你创建了大量的对象,但却由于自己的疏忽忘了将他们进行释放,可能会造成内存溢出)。

何为垃圾?

刚才说了,虚拟机会自动帮助我们进行垃圾的清除,那什么样的对象我们才可以称为是垃圾对象呢?

假如你创建了一个对象

Man m = new Man();

你用一个变量指向了这个对象,显然对于这个对象,你可以用变量m对这个对象进行利用,但过了一段时间,你执行了

m = null;

并且也并没有新的变量来指向刚才创建的对象。此时对于这个没有任何变量指向的对象,你觉得它还有用处吗?

显然,对于这种没有被变量指向的对象,它是一点卵用也没有的,它只能在随风漂流。

因此,对于这样的对象,我们就可以把它称为垃圾了,它早晚会被垃圾回收器给干掉。

怎么知道它已经是垃圾对象了?

假如代码是你自己编写的,你可能知道这个对象啥时候应该被抛弃,你可以随时让它成为垃圾对象。

但是,你毕竟是你,虚拟机则没那么智能。那虚拟机是如何知道的呢?

上面已经说了,没有变量引用这个对象时,它就是垃圾对象了,基于这个原理,我们可以这样做啊:

我们可以为这个对象设置一个计数器,初始值为0,假如有一个变量指向它,那么计数器就加1,如果这个变量不在指向它了,计数器就减1。那么我们就可以判断,如果这个计数器为0的话,那它就是垃圾对象了,否则就是有用的对象。

对于这种方法,我们称之为引用计数法

好吧,我们先来夸一夸引用计数法这种方法:

  1. 实现简单。
  2. 效率高(一个if语句就能解决的问题想不高效都难)。

不好意思,接下来得说说它那个致命的缺点

实际上,对于这种引用计数的方法,假如它遇到对象互相引用的话,是很难解决的。

先看一段代码:

Man m1 = new Man();
Man m2 = new Man();
//互相引用
m1.instance = m2;//假设Man有instance这个属性
m2.instance = m1;m1 = null;
m2 = null;
System.gc();//按道理对象应该被回收

这段代码m1和m2都指向null了,按道理两个对象已经是无用对象,应该被回收,但是,两个对象之间彼此有一个instance的属性互相牵引的对方,导致两个对象并没有被回收。

这个缺点够致命吧?

所以,虚拟机并没有采用这种引用计数的方法。

可达性分析

除了这种方法,我们还有其他的方法吗?

答案是有的,必须得有啊。这种方法就是传说中的可达性分析,(我靠,听名字是真的高级啊)。它的工作原理是这样的:

在程序开始时,会建立一个引用根节点(GC Roots),并构建一个引用图。当需要判断谁是垃圾时,我们可以从这个根节点进行遍历,如果没有被遍历到的节点则是垃圾对象,否则就是有用对象。如下图:

这个方法可以解决循环相互引用的问题,但是这个方法并没有引用计数法高效,毕竟要遍历图啊。

总结下判断是否为垃圾对象的算法:

  1. 引用计数法。
  2. 可达性分析。

何时进行垃圾回收

可能有人会觉得这个问题很奇怪,觉得看到垃圾就回收不是很好。对于这个我只能说:

  1. 看到房间有一点垃圾你会马上扫?还是等到某个时间点或者当垃圾积累到一定的数量再扫?
  2. 虚拟机可没那么智能可以马上识别这个对象是垃圾对象,它还得遍历所有对象才能知道有哪些是垃圾对象。

所以说,你总不能几秒(我们假设几秒是贼短的时间)就让虚拟机遍历一下所有对象吧?

这里先说明一下,当垃圾回收器在进行垃圾回收的时候,为了保证垃圾回收不受干扰,是会暂停所有线程的,此时程序无法对外部的请求进行响应。(因为你想啊,当你在可达性分析的时候,那些引用关系还在不断着变化,那不很难受)。

而且频繁的垃圾回收,对于有一些程序,是很影响用户体验的,例如你在玩游戏,系统动不动就停顿一下,怕你是要把这游戏给删了。

所以说,垃圾回收是会等到内存被使用了一定的比例的时候,才会触发垃圾回收。至于这个比例是多少,这可能就是人为规定的了。

怎么回收?

当我们标记好了哪些是垃圾,想要进行回收的时候,该怎么回收比较好呢?

可能有一些人就觉得奇怪,这还不简单,看见它是垃圾,直接回收不就得了。

其实这也不无道理,简单粗暴,直接回收。

是的,确实有这样的算法,看哪些是被我们标记的垃圾,看见了就直接回收。这种算法我们称之为标记--清除算法

标记-清除算法工作原理:就是先标记出所有需要回收的对象,然后在统一回收所有被标记过的对象。

不过,那些人你可别得意啊,因为这种方法虽然简单暴力,但它有个致命的缺点就是:

标记清除过后,会产生大量的不连续内存碎片,如果不连续的碎片过多的话,,可能会导致有一些大的对象存不进去。这样,会导致下面两个问题:

  1. 有些内存浪费了。
  2. 对象存不进去,会又一次触发垃圾回收。

复制算法

为了解决这种问题,另外一种算法出现了---复制算法。就是说,它会将可用的内存按容量划分成两块。然后每次只使用其中的一块,当这一块快用完的时候,就会触发垃圾回收,它会把还存活的对象全部复制到另外一块内存中去,然后把这块内存全部清理了。

这样,就不会出现碎片问题了。

居然帮我们解决了我们必须夸一下它:不仅帮我们解决了问题,而且实现上也简单、运行也高效。

但是(凡事都有个但是的),它也是有缺点的,缺点很明显,发现了没有。假如每次存活的对象都很少很少,那另外一块内存不是几乎没有用到?所以说,这种方法有可能导致另外一半内存几乎没用了。内存那么宝贵,这可是很严重的问题。

优化策略:可以告诉你,有研究显示,其实有98%的对象都是朝生夕死的,也就是说,每次存活的对象确实很少很少。既然我们都知道存活的对象很少很少了,那我们干嘛还1:1的比例来分配?所以说,HotShot虚拟机是默认按8:1的比例来分配的。这样,就不会出现很多内存没用到的问题了。

可能有人会说,万一占比为1/9的内存不够用了怎么办?不就没地方存那些活的对象?实际上,当内存不够用时,可以向其他地方借些内存来使用,例如老年代里的内存。

这里说明一下新生代和老年代:说白了,新生代就是刚刚创建不久的对象,而老年代是已经活了挺久的对象。也就是说,有一些对象是确实活的比较久的,对于这种对象,我们另外给它分配内存来养老,而且垃圾回收时,我们不用每次都来这里查找有没垃圾对象,因为这些对象是垃圾的几率会比较小。

下面在简单介绍另外两种算法:

  1. 标记-整理算法:这种算法和标记-清除算法类似,不过它把垃圾清除了之后,会让存活的对象往一个方向靠拢,以此来整理碎片。
  2. 分代收集算法:所谓分代就是把对象分成类似上面说的老年代和新生代,在新手代一般每次垃圾回收时死的对象一般都会比较多,而老年代会比较少,基于这种关系,我们就可以采取不同的算法来针对了。

总结下垃圾回收的几种算法:

  1. 标记-清除算法。
  2. 复制算法。
  3. 标记-整理算法。
  4. 分代收集算法。

最后给大家几种垃圾回收器

对于垃圾的回收,你是想一边运行程序其他代码一边进行垃圾回收?还是想把垃圾全收好再来执行程序的其他代码?虽然说最终使用cpu的时间是一样,但两种方式还是有区别的。

下面简单介绍几种垃圾回收器,看看他们都使用哪种方。

(1).Serial收集器

serial(串行),看这个英文单词就知道这是一个单线程收集器。也就是说,它在进行垃圾回收时,必须暂停其他所有线程。显然,有时垃圾回收停顿的比较久的话,这对于用户来说是很难受的。

(2).ParNew

这个收集器和Serial很类似,进行垃圾回收的时候,也是得暂停其他所有线程,不过,它可以多条线程工作进行垃圾回收。

(3).Parallel Scavenge收集器

parallel,并行的意思。也是可以多线程进行垃圾回收处理,但是它与ParNew不同。它会严格控制垃圾回收的时间与执行其他代码的时间之间的比例。我们来看一个名词:吞吐量

吞吐量 = 运行用户代码时间 / (运行用户代码时间 + 垃圾收集时间)。

也就是说,Parallet Scavenge收集器会严格控制吞吐量,至于这个吞吐量是多少,这个可以人为设置。

下面两个收集器重点介绍下

(4).CMS(Concurrent Mark Sweep)收集器

CMS收集器是基于“标记-清除”算法实现的,它的运作过程相对于前面几种收集器来说要更复杂一些,整个过程分为4个步骤,包括:

  1. 初始标记(CMS initial mark)
  2. 并发标记(CMS concurrent mark)
  3. 重新标记(CMS remark)
  4. 并发清除(CMS concurrent sweep)

其中初始标记、重新标记这两个步骤仍然需要暂停其他线程。但另外两个步骤可以和其他线程并发执行。初始标记仅仅只是标记一下GCRoots能直接关联到的对象,速度很快,并发标记阶段就是进行GC Roots Tracing的过程 (说白了就是把整个图都遍历了,找出没有的对象)

而重新标记阶段则是为了修正并发标记期间,因用户程序继续运作而导致标记产生变动的那一部分对象的标记记录,这个阶段的停顿时间一般会比初始标记阶段稍长一些,但远比并发标记的时间短。

由于整个过程中耗时最长的并发标记和并发清除过程中,收集器线程都可以与用户线程一起工作,所以总体上来说,CMS收集器的内存回收过程几乎是与与用户线程一起并发地执行。

(5).G1收集器

这个估计是最牛的收集器了。该收集器具有如下特点:

  1. 并行与并发:G1能充分利用现代计算器多CPU,多核的硬件优势,可以使用并发或并行的方式来缩短让其他线程暂停的优势。
  2. 分代收集:就是类似像分出新生代和老年代那样处理。
  3. 空间整合:采用了复制算法+标记-整合算法的特点来回收垃圾。就是整体采用标记-整理算法,局部采用复制算法
  4. 可预测停顿:这个就牛了,就是说,它能让使用者明确指定在一个长度为M毫秒的时间片段内,消耗在垃圾收集上的时间不超过N毫秒。

它的执行过程大体如下:

  1. 初始标记。
  2. 并发标记。
  3. 最终标记。
  4. 筛选回收。

这个流程和CMS很相似,它也是在初始标记最终标记需要暂停其他线程,但其他两个过程就可以和其他线程并发执行。

刚才我们说了G1收集器哪些优点,例如可预测停顿,这也使得筛选回收,是可以预测停顿垃圾回收的时间的,也就是说,停顿的时间是用户自己可以控制的,这也使得一般情况下,在筛选回收的时候,我们会暂停其他线程的执行,把所有时间都用到筛选回收上。

本次讲解到这里。

关注公我的众号:苦逼的码农,获取更多原创文章,后台回复"礼包"送你一份特别的资源大礼包。

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

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

相关文章

2058. 找出临界点之间的最小和最大距离

2058. 找出临界点之间的最小和最大距离 链表中的 临界点 定义为一个 局部极大值点 或 局部极小值点 。 如果当前节点的值 严格大于 前一个节点和后一个节点,那么这个节点就是一个 局部极大值点 。 如果当前节点的值 严格小于 前一个节点和后一个节点,…

tb计算机存储单位_如何节省数TB的云存储

tb计算机存储单位Whatever cloud provider a company may use, costs are always a factor that influences decision-making, and the way software is written. As a consequence, almost any approach that helps save costs is likely worth investigating.无论公司使用哪种…

Django Rest Framework(一)

一、什么是RESTful REST与技术无关,代表一种软件架构风格,REST是Representational State Transfer的简称,中文翻译为“表征状态转移”。 REST从资源的角度审视整个网络,它将分布在网络中某个节点的资源通过URL进行标识&#xff0c…

数据可视化机器学习工具在线_为什么您不能跳过学习数据可视化

数据可视化机器学习工具在线重点 (Top highlight)There’s no scarcity of posts online about ‘fancy’ data topics like data modelling and data engineering. But I’ve noticed their cousin, data visualization, barely gets the same amount of attention. Among dat…

python中nlp的库_用于nlp的python中的网站数据清理

python中nlp的库The most important step of any data-driven project is obtaining quality data. Without these preprocessing steps, the results of a project can easily be biased or completely misunderstood. Here, we will focus on cleaning data that is composed…

一张图看懂云栖大会·上海峰会重磅产品发布

2018云栖大会上海峰会上,阿里云重磅发布一批产品并宣布了新一轮的价格调整,再次用科技普惠广大开发者和用户,详情见长图。 了解更多产品请戳:https://yunqi.aliyun.com/2018/shanghai/product?spm5176.8142029.759399.2.a7236d3e…

怎么看另一个电脑端口是否通_谁一个人睡觉另一个看看夫妻的睡眠习惯

怎么看另一个电脑端口是否通In 2014, FiveThirtyEight took a survey of about 1057 respondents to get a look at the (literal) sleeping habits of the American public beyond media portrayal. Some interesting notices: first, that about 45% of all couples sleep to…

Java基础之Collection和Map

List:实现了collection接口,list可以重复,有顺序 实现方式:3种,分别为:ArrayList,LinkedList,Vector。 三者的比较: ArrayList底层是一个动态数组,数组是使用…

20155320《网络对抗》Exp4 恶意代码分析

20155320《网络对抗》Exp4 恶意代码分析 【系统运行监控】 使用schtasks指令监控系统运行 首先在C盘目录下建立一个netstatlog.bat文件(由于是系统盘,所以从别的盘建一个然后拷过去),用来将记录的联网结果格式化输出到netstatlog.…

tableau 自定义省份_在Tableau中使用自定义图像映射

tableau 自定义省份We have been reading about all the ways to make our vizzes in Tableau with more creativity and appeal. During my weekly practice for creating viz as part of makeovermonday2020 community, I came across geographical data which in way requir…

2055. 蜡烛之间的盘子

2055. 蜡烛之间的盘子 给你一个长桌子,桌子上盘子和蜡烛排成一列。给你一个下标从 0 开始的字符串 s ,它只包含字符 ‘’ 和 ‘|’ ,其中 ’ 表示一个 盘子 ,’|’ 表示一支 蜡烛 。 同时给你一个下标从 0 开始的二维整数数组 q…

Template、ItemsPanel、ItemContainerStyle、ItemTemplate

原文:Template、ItemsPanel、ItemContainerStyle、ItemTemplate先来看一张图(网上下的图,加了几个字) 实在是有够“乱”的,慢慢来理一下; 1、Template是指控件的样式 在WPF中所有继承自contentcontrol类的控件都含有此属性,&#…

熊猫烧香分析报告_熊猫分析进行最佳探索性数据分析

熊猫烧香分析报告目录 (Table of Contents) Introduction 介绍 Overview 总览 Variables 变数 Interactions 互动互动 Correlations 相关性 Missing Values 缺失值 Sample 样品 Summary 摘要 介绍 (Introduction) There are countless ways to perform exploratory data analys…

白裤子变粉裤子怎么办_使用裤子构建构建数据科学的monorepo

白裤子变粉裤子怎么办At HousingAnywhere, one of the first major obstacles we had to face when scaling the Data team was building a centralised repository that contains our ever-growing machine learning applications. Between these projects, many of them shar…

支持向量机SVM算法原理及应用(R)

支持向量机SVM算法原理及应用(R) 2016年08月17日 16:37:25 阅读数:22292更多 个人分类: 数据挖掘实战应用版权声明:本文为博主原创文章,转载请注明来源。 https://blog.csdn.net/csqazwsxedc/article/detai…

mad离群值_全部关于离群值

mad离群值An outlier is a data point in a data set that is distant from all other observations. A data point that lies outside the overall distribution of the dataset. Or in a layman term, we can say, an outlier is something that behaves differently from th…

青年报告_了解青年的情绪

青年报告Youth-led media is any effort created, planned, implemented, and reflected upon by young people in the form of media, including websites, newspapers, television shows, and publications. Such platforms connect writers, artists, and photographers in …

post提交参数过多时,取消Tomcat对 post长度限制

1.Tomcat 默认的post参数的最大大小为2M, 当超过时将会出错,可以配置maxPostSize参数来改变大小。 从 apache-tomcat-7.0.63 开始,参数 maxPostSize 的含义就变了: 如果将值设置为 0,表示 POST 最大值为 0,…

map(平均平均精度_客户的平均平均精度

map(平均平均精度Disclaimer: this was created for my clients because it’s rather challenging to explain such a complex metric in simple words, so don’t expect to see much of math or equations here. And remember that I try to keep it simple.免责声明 &#…

Sublime Text 2搭建Go开发环境,代码提示+补全+调试

本文在已安装Go环境的前提下继续。 1、安装Sublime Text 2 2、安装Package Control。 运行Sublime,按下 Ctrl(在Tab键上边),然后输入以下内容: import urllib2,os,hashlib; h 7183a2d3e96f11eeadd761d777e62404 e330…