JVM内存回收机制及回收器-一目了然

一、概述

内存回收,分析出所以然,为什么如此设计,内存回收,如整理屋子。用户就是系统,其实和普通的系统没有大区别。

需求: 正确 高效(不能对用户线程有较大的影响)

二、设计

我来设计的话,一些基本的问题。 哪些对象需要被回收? 谁来回收? JVM 在哪里回收? 一般堆上,栈上回收比较困难 在什么时候回收? 怎么回收?

第一个问题:

哪些对象需要被回收?

我们需要先标记出来, 大致有两个标记的算法, 第一:引用计算法。就是 引用了就加1,减少一个引用就减1.但是无法解决 互相引用的问题。故JAVA没有采用了。为什么别的语言采取了,我也不知道。 第二:根搜索算法 从根 GC roots开始找,如果是根不可达的对象就是 可回收的对象。JAVA JVM就是采取这种方式实现的。

第二问题:

谁来回收?

那肯定要一个名称,叫垃圾回收器,运行在回收线程里面。垃圾回收器具体要解决什么时候做,如何回收的问题。

第三个问题:在哪里回收?

一般在堆上。栈上回收比较困难,栈上也可以进行内存回收,不过条件太苛刻了。

第四个问题与第五个问题一起回答了:

在什么时候回收? 基本是在内存不够用的时候。每个收集器还所有不同。 垃圾回收基本的思想是:stop-the-world再回收,就如:不能在打扫卫生的时候同时再仍新的垃圾。 但是CMS、与将出世的 G1会打破这个界限,实现 边打扫卫生,还边扔垃圾。

怎么回收:一般有三个基本的算法: 1、标记清除:直接标记,再清除掉需要回收的内存。(产生大量的内存碎片) 2、标记复制:用两个一样的大小的内存,总只有一块再用,回收时没有回收的部分直接复制到另一块上去。 3、标记整理:先标记,让所有存活的对象向一段移动,然后直接清除掉边界外的内存。 java中的处理: 根据对象的存活生命周期将不同的内存分为几块。新生代与老年代 新生代有大量的对象死去,只有少量的对象存活,所以用复制算法。 老年代对象存活周期长,没有额外的担保空间,就必须用 标记清除 与标记整理 的算法。 以下再描述下: 为了解决对象生命周期长短对回收的影响,在hotSpot中主要分为了: young与old区。 young区的大部分对象基本可以回收,所以采取了标记复制算法。(复制算法就是浪费了50%的内存),为了不浪费太多的内存,采取了 两个交换区与一个Eden区。交换区互换地存下每次young gc留下来的对象,如果存不下就需要 old区来担保了(多余的对象直接进入old区)。 old区内存一般停留比较久,内存也比较大,他也找不到担保内存了,也不可能把内存分为两部分互相拷贝。所以一开始就采取了标记整理的算法。(开始一直认为标记清除 算法会产生大量的内存碎片,会很不好,后来回收器设计者的想法可能变了)。 根据线程数为单线程与多线程,追求 目标不同。先后有: young区:Serial(单线程)、parNew(多线程)、Parallel Scavenge(多线程,追求高的CPU吞吐量,与前者的并行是不同的实现)。 Old区:Serial Old(单线程,是Serial的Old版本)、Parallel Old(多线程,追求高的CPU吞吐量,是Parallel Scavenge的Old版本)

问题1:?为什么parNew没有Old的版本呢? 可能是 Parallel Old 已经好用了,没有必要再弄一个parNew Old吧。不过有点牵强。还有原因就是 没有资源弄了,大家都开发g1去了。嘿嘿。。。 问题2:?为什么young区有两个多线程的回收器? 可能是:他们的来源不一样,一个是自己实现的,一个用了部分Exact VM的分代式GC框架的思想。这个也是Parallel Scavenge与CMS不兼容的原因。

CMS(coururrent Mark Sweep)收集器,可以容许 用户线程与回收线程在回收的大部分时间里并行运行。

算法是: 标记清除,因为不需要移动对象的内存,所以实现并发处理相对简单些。 CMS大致的过程是: 初始标记,并发标记(与用户线程并发运行),重新标记,并发清除(与用户线程并发运行)。

在并发清除中,(用户线程还在运行)会产生浮动垃圾,垃圾一多,用户线程不能申请内存时,会产生 Concurrent Mode Failure错误,再会触发一次Serial Old Full GC,这个也是下图:CMS与Serial Old连着的原因.

【 为什么会触发一个 单线程的 full gc呢.估计原因是没有时间做多线程的。 后来把资源投入到了 Garbage Collection的研发上去了。

在jdk7中估计会产生重量级的垃圾回收器Garbage First简称G1。此改进了CMS的内存碎片的问题,把算法由 标记清除,变为了标记整理。主要是 把堆再分为不同的小区,对垃圾较多的优先回收。基本能实现 实时java的垃圾收集器

下图展示了目前jdk1.6的回收器。回收器连线表示可以互相协同作战。旁边有一些参数主要作为调试用。

三、结尾

没有一个垃圾回收器能解决所有的问题,针对不同的场景需要不同的垃圾回收器。单线程的Serial与Serial Old也不是不好,在单CPU下他就是最好的。 也希望JAVA能推出新一代的垃圾回收器,为我们高效低回垃回收内存。

四、参考资料

《深入理解java虚拟机》 Garbage Collection:http://labs.oracle.com/jtech/pubs/#gc

原文发布于微信公众号 - 马哥Linux运维(magedu-Linux)

原文发表时间:2015-03-18

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏向治洪

android软件开发之webView.addJavascriptInterface循环渐进【一】

首先必要的啰嗦几句,这几天写VC写的累的要死,突然间不想再写想VC了,手里面有一个andriod的手机天天玩到半夜,却从来没有写过这方面的程序,真的是悲哀啊。所...

4037
来自专栏IT笔记

JAVA工作三年面试(二)

这里讲述下第二家公司的面试,这是一家大型互联网公司,简称W,一般像博主这样的传统行业去跳到这种公司简直是要跪舔的节奏,所以从一开始就带着一份敬仰之情去面试。由于...

4427
来自专栏阿杜的世界

G1的一些概念一、概念解释二、参数学习

821
来自专栏无题

GC优化案例1:Major GC和Minor GC频繁

对GC优化的案例进行的系列总结(一): GC优化案例1:Major GC和Minor GC频繁 确定目标 服务情况:Minor GC每分钟100次 ,Majo...

8236
来自专栏架构师之旅

JVM内存管理------GC算法精解

相信不少猿友看到标题就认为LZ是标题党了,不过既然您已经被LZ忽悠进来了,那就好好的享受一顿算法大餐吧。不过LZ丑话说前面哦,这篇文章应该能让各位彻...

2088
来自专栏小狼的世界

使用Python读取Mp3的标签信息

MP3是音频文件最流行的格式,它的全称是 MPEG layer III。但是这种格式不支持对于音频内容的描述信息,包括歌曲名称、演唱者、专辑等等。

1883
来自专栏java一日一条

成为JavaGC专家(1)—深入浅出Java垃圾回收机制

对于Java开发人员来说,了解垃圾回收机制(GC)有哪些好处呢?首先可以满足作为一名软件工程师的求知欲,其次,深入了解GC如何工作可以帮你写出更好的Java应用...

1702
来自专栏CSDN技术头条

解析大型.NET ERP系统 20条数据库设计规范

数据库设计规范是个技术含量相对低的话题,只需要对标准和规范的坚持即可做到。当系统越来越庞大,严格控制数据库的设计人员,并且有一份规范书供执行参考。在程序框架中,...

2987
来自专栏美团技术团队

【你问我答】你与Java大牛的距离,只差这24个问题

点击上方“公众号”可以订阅哦 上周我们做了第一期“你问我答”活动,没想到有那么多读者进行了提问,受宠若惊。 问题比较多也比较杂,王锐老师很认真地给出了一些答案,...

45113
来自专栏我是攻城师

透视JVM之垃圾回收

3645

扫码关注云+社区

领取腾讯云代金券