上节我们介绍了JVM垃圾回收的原则,还有几个垃圾收集算法:标记-清除算法、复制算法、标记整理算法、分代收集算法;现在将要说HotSpt的垃圾收集器,这小节将只是理论。

Java虚拟机规范对垃圾收集器的具体实现并没有任何规定,所以不同厂商、不同版本的虚拟机提供的垃圾收集器会有很大的不同。下面所介绍的收集器只是HotSpt1.7的垃圾收集器。

    HotSpot堆的瓜分

HotSpt它把内存空间分为几个区域:新生代、老年代、永久代;上节中也说到了分代垃圾收集算法的主要思想按对象的生命周期来进行分组;

如上图JVM把堆划分为Young、Old、Perm三大区域,对应着不能年龄的对象;然后又把Young分为:Eden、Survivor From、Survivor To三小块;各个区域存放对象的区别如下:

  • Young区,所有新创建的对象都存储在Eden区域中,当Eden满后将会触发minor GC把Eden中存活的对象复制到一个Survivor中,然后另一个Survivor存活对象也复制到这个中,始终保持一个Survivor区域为空的。
  • Old区存放的是Survivor满后触发minor GC后依然存活的对象,如果从Eden复制到Survivor的对象存不了也可以直接存到Old区中等。Old区满了就会触发Full GC回收整个堆内存。
  • Perm区存储类、方法、等的元信息,Perm也会触发Full GC进行垃圾回收。

Sun有对各个区域给出建议的大小,Young区域为整个堆的1/4,Young中的Survivor为Young区域的1/8,安装JDK的时候有自带了visualvm工具,可以安装Visual GC插件来查看到JVM各个区域的垃圾回收情况,可以看到内存大小、GC时间、已使用大小、剩余大小等等信息如图:

 

    垃圾收集器

HotSpot提供了七种类垃圾收集器:Serial 收集器、ParNew 收集器、Parallel Scavenge收集器、Serial Old收集器、Parallel Old 收集器、CMS 收集器、G1 收集器。

Serial 收集器是比较古老的一种收集器,不过到现在他还是JVM client模式中默认新生代的GC算法, Serial是单线程的,它在进行垃圾回收工作时会暂停所有其他工作,Sum称为:“Stop The World”,直到回收任务结束,然后Serial工作时占用的时间比较多但它比较简单新生代内存不大的情况下回收工作时间还是短到可以接收的,基本一秒以内。

ParNew 收集器与Serial Collector唯一不同的就是Serial Collector是单线程的,ParNew Collector是多线程的,ParNew Collector是JVM Server模式中默认的新生代GC算法。

Parallel Scavenge收集器 也是新生代收集算法,使用复制算法、并行的多线程,它的优势在于提高吞吐量,GC停顿的时间越短吞吐量就会越高,

Serial Old收集器为Serial的老年代版本,单线程、“标记-整理”算法,在Client模式下为虚拟机使用。

Parallel Old 收集器为Parallel Scavenge的老年代版本,使用多线程、“标记-清除算法”,

CMS(Concurrent Mark Sweep收集器是以最短停顿时间为目标的收集器,使用了“标记清除”算法实现,不过这个收集器比前面几个收集器都要复杂,运作过程有这么几个步骤:

1、  初始标记(CMS initial mark)

2、  并发标记(CMS concurrent mark)

3、  重新标记(CMS remark)

4、  并发清除(CMS concurrent sweep)

在初始标记、重新标记的时候会“Stop The World”,初始标记标记出GC Roots能直接关联到的对象,并发标记进行GC Roots Tracing,重新标记修复在程序继续运行导致标记的变动,CMS也有不好的地方就是CMS会占用较多的CPU由于CMS是使用标记清除算法实现的,所以可能会导致较多的碎片。

G1收集器JDK1.7发布的时候才退出的算法,可以说是比较新的技术,相比CMS G1不会产生碎片,因为他使用的是“标记-整理”算法,G1还有就是能比较精确的空间停顿时间可以在不牺牲吞吐量的情况下进行垃圾回收,G1把整个Java堆(新生代、老年代)瓜分为多个独立区域,跟踪这些区域的垃圾堆积程度,然后维护一个优先列表,根据允许的时间优先回收垃圾最多的区域。

内存分配策略

内存的分配规则不是百分之百固定的,它取决与虚拟机的相关参数配置还有使用的垃圾收集器组合。这里说的只是最普遍的内存分配规则,这里只是说些理论,在下篇文章将会用代码去验证。

    Eden优先分配

绝大多数情况下对象创建的时候在Eden区域分配,当分配的时候Eden中空间不足时将触发Minor GC,

    较大对象直接进入老年代

较大对象:需要使用大量连续的内存空间的Java对象,常见的有:很长的字符串、数组,写代码的时候能避免尽量避免短命较大对象,因为大对象常常会引发GC。

    生命周期较长的对象进入老年代

分代垃圾收集的思想就是按对象的生命周期来分开管理,虚拟机为每个对象定义了一个对象年龄计数器,对象在Eden区中经过一次Minor GC后仍存活并复制到Survivor中,对象年龄就为1,对象每在Survivor中度过一次Minor GC年龄将加1,当年龄到一定值(默认15)的时候对象将晋升到老年代。阀值可以通过参数设置,后面将介绍到。

   动态年龄判定

虚拟机并不定死说必须达到MaxTenuringThreshold年龄才能晋升老年代;如在Survivor空间中相同年龄所有对象大小总和大于Survivor空间的一半,大于或等于该年龄的对象就可以直接进入老年代中,无需等到指定的年龄。

   空间担保分配

年轻代在发生Minor GC时,虚拟机会检测每次晋升到老年代的平均大小是否大于老年代剩余的存储空间,比老年代剩余空间大则改为直接Full GC,如果小,则看HandlePromotionFailure设置是否允许担保失败,是则只会进行Minor GC,否则也要改为进行一次Full GC。

文章首发地址:Solinx

http://www.solinx.co/archives/58

JVM探索之内存管理(三)的更多相关文章

  1. JVM探索之——内存管理(一)

    本系列的第一篇文章,预计本系列最后面会有两三个案例. Java与C.C++不一样Java不需要Coder进行手动内存管理,而这一切都交给JVM进行自动内存管理,这从某种程度上来说也减轻了我们Coder ...

  2. JVM探索之——内存管理(二)

    上篇文章我们介绍了JVM所管理的内存结构也就是运行时数据区(Run-Time Data Areas),现在我们将介绍JVM的内存分配与回收静态内存分配与动态内存分配 JVM的内存分配主要分为两种:静态 ...

  3. JVM介绍&自动内存管理机制

    1.介绍JVM(Java Virtual Machine,Java虚拟机) JVM是Java Virtual Machine的缩写,通常成为java虚拟机,作为Java可以进行一次编写,到处执行(Wr ...

  4. Linux内存描述之内存区域zone--Linux内存管理(三)

    1 内存管理域zone 为了支持NUMA模型,也即CPU对不同内存单元的访问时间可能不同,此时系统的物理内存被划分为几个节点(node), 一个node对应一个内存簇bank,即每个内存簇被认为是一个 ...

  5. Linux内存描述之内存区域zone–Linux内存管理(三)

    服务器体系与共享存储器架构 日期 内核版本 架构 作者 GitHub CSDN 2016-06-14 Linux-4.7 X86 & arm gatieme LinuxDeviceDriver ...

  6. PHP内核探索:内存管理开篇

    内存是计算机非常关键的部件之一,是暂时存储程序以及数据的空间,CPU只有有限的寄存器可以用于存储计算数据,而大部分的数据都是存储在内存中的,程序运行都是在内存中进行的.和CPU计算能力一样, 内存也是 ...

  7. COCOS学习笔记--Cocod2dx内存管理(三)-Coco2d-x内存执行原理

    通过上两篇博客.我们对Cocos引用计数和Ref类.PoolManager类以及AutoreleasePool类已有所了解,那么接下来就通过举栗子来进一步看看Coco2d-x内存执行原理是如何的. / ...

  8. Java Core - JVM运行时内存管理

    在读正文之前,阅读以下两篇博客学习并理解堆栈.作用域.本地方法的概念. 作用域:https://www.cnblogs.com/AlanLee/p/6627949.html 操作数栈:https:// ...

  9. jvm之自动内存管理

    一.运行时数据区 程序计数器(线程私有) 1.程序计数器占用jvm内存较小,主要用来记录当前线程所执行的字节码的位置,因为jvm的多线程都是通过cpu对线程进行来回切换,所以在某个确定的时间cpu只会 ...

随机推荐

  1. 第 1 章 HTML5 概述

    学习要点: 1.HTML5 的历史 2.HTML5 的功能 3.HTML5 的特点 4.课程学习问题 主讲教师:李炎恢 HTML5 是继 HTML4.01 和 XHTML1.0 之后的超文本标记语言的 ...

  2. Scalaz(14)- Monad:函数组合-Kleisli to Reader

    Monad Reader就是一种函数的组合.在scalaz里函数(function)本身就是Monad,自然也就是Functor和applicative.我们可以用Monadic方法进行函数组合: i ...

  3. The template engine

    Play has an efficient templating system which allows to dynamically generate HTML, XML, JSON or any ...

  4. 支持10种格式的 HTML 表格导出 jQuery 插件

    HTML 表格导出 jQuery 插件可以帮助用户导出 HTML 表格到 JSON.XML.PNG.CSV.TXT.SQL.MS-Word.MS-Excel.MS-PowerPoint 和 PDF 格 ...

  5. mongodb系列3 mongo mongoskin 连接以及连接数的问题进阶

    1)使用mongodb连接mongo var mongo = require('mongodb'), //引入mongodb dbHost = '127.0.0.1', dbPort = 27017; ...

  6. Moqui简介

    Moqui简介 Moqui是一个生态系统理念,是需要一系列的能够用于构建企业自动化办公的开源软件的组合,如:eCommerce, ERP, CRM, SCM, MRP, EAM, POS, 等等. 架 ...

  7. ALV中处理过滤掉的行

    有时候我们在ALV的时候,客户会对输出的数据进行二次筛选,这时候如果我们做全选(checkbox)系统会把我们过滤掉得数据也选择: 用下面的method就可避免此问题: DATA:it_rows TY ...

  8. Sharepoint学习笔记—习题系列--70-576习题解析 -(Q88-Q91)

    Question 88  You are designing a SharePoint 2010 application that stores data in a list named Base L ...

  9. yii cookie ,session 操作

    一,在Yii中使用session 1,CHttpSession 与原生态php5的session使用差别是,php5使用session_start();$_session['key'] = $valu ...

  10. flashdevelop生成swc库

    flashdevelop没有直接支持生成swc的工程,但flashdevelop生成swc也比较方便,不用任何插件. swc库是由 flexsdk的compc.exe生成的,其实我们通过这个命令行也可 ...