JVM 调优系列之图解垃圾回收

2017 年 10 月 21 日 开源中国 OSC - wier


摘要: jvm必知系列,总结一些常见jvm回收机制,方便查阅


从这篇开始我们开始探讨一些jvm调优的问题。在jvm调优中一个离不开的重点是垃圾回收,当垃圾回收成为系统达到更高并发量的瓶颈时,我们就需要对jvm中如果进行“自动化”垃圾回收技术实施必要的监控和调节。


对于调优之前,我们必须要了解其运行原理,java 的垃圾收集Garbage Collection 通常被称为“GC”,它诞生于1960年 MIT 的 Lisp 语言,经过半个多世纪,目前已经十分成熟了。因此本篇主要从这三个方面来了解:


1. 哪些对象需要被回收?

2. 什么时候回收?

3. 如何回收?


谁要被回收


java虚拟机在执行java程序的过程中会把它所管理的内存划分为若干个不同是数据区域,这些区域有各自各自的用途。主要包含以下几个部分组成:



程序计数器

程序计数器占用的内存空间我们可以忽略不计,它是每个线程所执行的字节码的行号指示器。


虚拟机栈

java的虚拟机栈是线程私有的,生命周期和线程相同。它描述的是方法执行的内存模型。同时用于存储局部变量、操作数栈、动态链接、方法出口等。


本地方法栈

本地方法栈,类似虚拟机栈,它调用的是是native方法。


堆是jvm中管理内存中最大一块。它是被共享,存放对象实例。也被称为“gc堆”。垃圾回收的主要管理区域


方法区

方法区也是共享的内存区域。它主要存储已被虚拟机加载的类信息、常量、静态变量、即时编译器(jit)编译后的代码数据。


以上就是jvm在运行时期主要的内存组成,我们看到常见的内存使用不但存在于堆中,还会存在于其他区域,虽然堆的管理对程序的管理至关重要,但我们不能只局限于这一个区域,特别是当出现内存泄露的时候,我们除了要排查堆内存的情况,还得考虑虚拟机栈的以及方法区域的情况。


知道了要对谁以及那些区域进行内存管理,我还需要知道什么时候对这些区域进行垃圾回收。


什么时候回收


在垃圾回收之前,我们必须确定的一件事就是对象是否存活?这就牵扯到了判断对象是否存活的算法了。


引用计数算法

给对象中添加一个引用计数器,每当有一个地方引用它时,计数器+1,当引用失效,计数器-1.任何时刻计数器为0的对象就是不可能再被使用的。


优点:实现简单,判定效率高效,被actionscript3和python中广泛应用。

缺点:无法解决对象之间的相互引用问题。java没有采纳


可达性分析算法

通过一系列称为“GC Roots”的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链,当一个对象到GCRoots没有任何引用链相连的时候,则证明此对象是不可用的。


比如如下,右侧的对象是到GCRoot时不可达的,可以判定为可回收对象。



在java中,可以作为GCRoot的对象包括以下几种:


* 虚拟机栈中引用的对象。

* 方法区中静态属性引用的对象。

* 方法区中常量引用的对象。

* 本地方法中JNI引用的对象。


基于以上,我们可以知道,当当前对象到GCRoot中不可达时候,即会满足被垃圾回收的可能。


那么是不是这些对象就非死不可,也不一定,此时只能宣判它们存在于一种“缓刑”的阶段,要真正的宣告一个对象死亡。至少要经历两次标记:


第一次:对象可达性分析之后,发现没有与GCRoots相连接,此时会被第一次标记并筛选。

第二次:对象没有覆盖finalize()方法,或者finalize()方法已经被虚拟机调用过,此时会被认定为没必要执行。


如何回收


上述的两点讲解之后,我们大概明白了,哪些对象会被回收,以及回收的依据是什么,但回收的这个工作实现起来并不简单。


首先它需要扫描所有的对象,鉴别谁能够被回收,其次在扫描期间需要 ”stop the world“ 对象能被冻结,不然你刚扫描,他的引用信息有变化,你就等于白做了。


分代回收

我们从一个object1来说明其在分代垃圾回收算法中的回收轨迹。


1、object1新建,出生于新生代的Eden区域。



2、minor GC,object1 还存活,移动到Fromsuvivor空间,此时还在新生代。



3、minor GC,object1 仍然存活,此时会通过复制算法,将object1移动到ToSuv区域,此时object1的年龄age+1。



4、minor GC,object1 仍然存活,此时survivor中和object1同龄的对象并没有达到survivor的一半,所以此时通过复制算法,将fromSuv和Tosuv 区域进行互换,存活的对象被移动到了Tosuv。



5、minor GC,object1 仍然存活,此时survivor中和object1同龄的对象已经达到survivor的一半以上(toSuv的区域已经满了),object1被移动到了老年代区域。



6、object1存活一段时间后,发现此时object1不可达GcRoots,而且此时老年代空间比率已经超过了阈值,触发了majorGC(也可以认为是fullGC,但具体需要垃圾收集器来联系),此时object1被回收了。fullGC会触发 stop the world。



在以上的新生代中,我们有提到对象的age,对象存活于survivor状态下,不会立即晋升为老生代对象,以避免给老生代造成过大的影响,它们必须要满足以下条件才可以晋升:


1、minor gc 之后,存活于survivor 区域的对象的age会+1,当超过(默认)15的时候,转移到老年代。

2、动态对象,如果survivor空间中相同年龄所有的对象大小的综合和大于survivor空间的一半,年级大于或等于该年级的对象就可以直接进入老年代。


以上采用分代垃圾收集的思想,对一个对象从存活到死亡所经历的历程。期间,在新生代的时刻,会用到复制算法,在老年代时,有可能会用到标记-清楚算法(mark-sweep)算法或者标记-整理算法,这些都是垃圾回收算法基于不同区域的实现,我们看下这几种回收算法的实现原理。


垃圾回收算法


标记清除法(Mark-Sweep)

标记清除法是垃圾回收算法的思想基础。标记清除算法将垃圾分为两个阶段:标记阶段和清除阶段。


标记阶段,通过根节点,标记所有从根节点开始的可达对象,未标记过的对象就是未被引用的垃圾对象。


清除阶段,清除所有未被标记的对象。



复制算法(Copying)

复制算法是,将原有的内存空间分为两块,每次只使用其中一块,在垃圾回收时,将正在适用的内存中存活对象复制到未使用的内存块,然后清除使用的内存块中所有的对象。



标记压缩算法(Mark-Compact)



标记压缩算法是一种老年代的回收算法。


标记阶段和标记清除算法一致,对可达对象做一次标记。


清理阶段,为了避免内存碎片产生,将所有的存活对象压缩到内存的一端。


垃圾收集器


垃圾收集器是内存回收的具体实现,不同的厂商提供的垃圾收集器有很大的差别,一般的垃圾收集器都会作用于不同的分代,需要搭配使用。以下是各种垃圾收集器的组合方式:




各种组合的优缺点:



以上优缺点来自:http://www.importnew.com/23752.html



推荐阅读

放弃 Python 转向 Go?有人给出了 9 大理由

区块链?人工智能?2018 年十大技术趋势

9 大跨平台移动 App 开发工具推荐

一张思维导图,让正则表达式不再难懂

vue 指令基本使用大全

点击“阅读原文”查看更多精彩内容

登录查看更多
0

相关内容

Java 虚拟机(Java Virtual Machine)是一个虚构出来的计算机,通过在实际的计算机上仿真模拟各种计算机功能来实现的。
打怪升级!2020机器学习工程师技术路线图
专知会员服务
98+阅读 · 2020年6月3日
商业数据分析,39页ppt
专知会员服务
159+阅读 · 2020年6月2日
TensorFlow Lite指南实战《TensorFlow Lite A primer》,附48页PPT
专知会员服务
69+阅读 · 2020年1月17日
智能交通大数据最新论文综述-附PDF下载
专知会员服务
104+阅读 · 2019年12月25日
【大规模数据系统,552页ppt】Large-scale Data Systems
专知会员服务
60+阅读 · 2019年12月21日
【干货】大数据入门指南:Hadoop、Hive、Spark、 Storm等
专知会员服务
95+阅读 · 2019年12月4日
在K8S上运行Kafka合适吗?会遇到哪些陷阱?
DBAplus社群
9+阅读 · 2019年9月4日
浅谈 Kubernetes 在生产环境中的架构
DevOps时代
11+阅读 · 2019年5月8日
基于动画图解常用的机器学习算法
人工智能前沿讲习班
5+阅读 · 2018年12月26日
为什么分布式一定要有消息队列?
互联网架构师
4+阅读 · 2018年7月5日
图解机器学习的常见算法
机器学习算法与Python学习
5+阅读 · 2018年4月2日
图解机器学习
深度学习世界
3+阅读 · 2017年11月24日
BAT机器学习面试1000题系列(第116~120题)
七月在线实验室
16+阅读 · 2017年10月24日
Music Transformer
Arxiv
5+阅读 · 2018年12月12日
Arxiv
3+阅读 · 2017年12月18日
VIP会员
相关VIP内容
打怪升级!2020机器学习工程师技术路线图
专知会员服务
98+阅读 · 2020年6月3日
商业数据分析,39页ppt
专知会员服务
159+阅读 · 2020年6月2日
TensorFlow Lite指南实战《TensorFlow Lite A primer》,附48页PPT
专知会员服务
69+阅读 · 2020年1月17日
智能交通大数据最新论文综述-附PDF下载
专知会员服务
104+阅读 · 2019年12月25日
【大规模数据系统,552页ppt】Large-scale Data Systems
专知会员服务
60+阅读 · 2019年12月21日
【干货】大数据入门指南:Hadoop、Hive、Spark、 Storm等
专知会员服务
95+阅读 · 2019年12月4日
相关资讯
在K8S上运行Kafka合适吗?会遇到哪些陷阱?
DBAplus社群
9+阅读 · 2019年9月4日
浅谈 Kubernetes 在生产环境中的架构
DevOps时代
11+阅读 · 2019年5月8日
基于动画图解常用的机器学习算法
人工智能前沿讲习班
5+阅读 · 2018年12月26日
为什么分布式一定要有消息队列?
互联网架构师
4+阅读 · 2018年7月5日
图解机器学习的常见算法
机器学习算法与Python学习
5+阅读 · 2018年4月2日
图解机器学习
深度学习世界
3+阅读 · 2017年11月24日
BAT机器学习面试1000题系列(第116~120题)
七月在线实验室
16+阅读 · 2017年10月24日
Top
微信扫码咨询专知VIP会员