专栏首页北京马哥教育JVM内存回收机制及回收器-一目了然

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)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

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

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

我来说两句

0 条评论
登录 后参与评论

相关文章

  • python实现生成图片路径和对应标签

    学计算机的同学都知道图片的路径更改特别麻烦,尤其要对应到相应的标签,这个让人炸花了眼,今天马哥python的老师搜集了一下素材,接下来就会通过python语言直...

    小小科
  • Kickstart+PXE自动部署CentOS6.6

    生产环境中对于部署大量的相同系统的服务器,如果逐台安装操作系统的话是非常浪费时间的工作,还好CentOS提供了无人值守安装系统的功能,下面就详细介绍一下配置步骤...

    小小科
  • 浅谈小白如何读懂Redis高速缓存与持久化并存及主从高可用集群

    一、简介 Redis是一个基于键值(K-V)的高速缓存软件,和他具有相同功能的软件有memcached,但其支持更为复杂的数据结构,例如:List,set,s...

    小小科
  • 程序猿的日常——JVM内存模型与垃圾回收

    Java开发有个很基础的问题,虽然我们平时接触的不多,但是了解它却成为Java开发的必备基础——这就是JVM。在C++中我们需要手动申请内存然后释放内存,否则...

    用户1154259
  • [我的面试宝典] 我是如何去看《深入理解Java虚拟机》这本书的

    最近公众号收到了很多留言,有的同学想知道我是如何看书,如何学习的,也有的同学想知道我的项目经验和一些技巧。其实,这都不是问题。微信公众号一天只能推送一次...

    乔戈里
  • 腾讯云携手CODING,云端IDE——Cloud Studio初体验

    4月16日,腾讯云与CODING宣布达成战略合作,共同发布以腾讯云云服务器为基础的国内第一款完全基于云端的IDE工具:Cloud Studio的beta版本。

    苏易北
  • 介绍Salesforce Lightning for Outlook

    你永远没有足够的时间去处理更多的工作和家庭之间的平衡。然而事实上时间总是会有的。问题的关键是:你将如何去利用时间?

    臭豆腐
  • 原码 反码 补码 移码

    1、正数的原码、补码、反码均为其本身; 2、负数(二进制)的原码、补码、反码公式: 反码 = 原码(除符号位外)每位取反 补码 = 反码 + 1 反码 =...

    用户1215536
  • Java初中级面试题(2)

    芋道源码
  • 金融科技&大数据产品推荐:金融魔方 ---专业的金融SaaS服务平台

    在金融牌照合规的基础上,链接银行、保险等金融机构核心业务系统,将合规的金融账户、金融产品、交易支付系统、风控、清结算系统等复杂功能集成为一套成熟、合规、可一键接...

    数据猿

扫码关注云+社区

领取腾讯云代金券