上节我们介绍了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. css知多少(2)——学习css的思路

    两周之前写过该系列的第一篇,其实当时只是一个想法,这段时间迟迟未更新,是在思考一个解决过程.现在初有成效,就开更吧. 1. 一个段子 开题不必太严肃,写博客也不像写书,像聊天似的写东西是最好的表达方式 ...

  2. angular学习的一些小笔记(中)之ng-init

    ng-init是给angular执行给定的表达式,初始化变量的值 <!DOCTYPE html> <html> <head> <meta charset='U ...

  3. 8种效果实例-jQuery anoSlide 焦点图轮播

    anoslide是一款可调节效果至任意宽度大小,支持图文混合内容显示的图片轮播插件. 在线实例 单个 多个 动画延迟 自动播放 显示分页 显示标题 延迟加载 自适应高度 使用方法 <div cl ...

  4. JavaScript学习笔记-面向对象的模块化编程

    面向对象的模块化编程 模块是一个独立的JS文件,模块文件可以包含一个类定义.一组相关的类.一个实用函数库.一些待执行的代码 模块化的目标:支持大规模的程序开发,处理分散源代码的组装,并能让代码正确执行 ...

  5. javascript 对象初探 (四)--- 内建对象之旅之Array

     我们不要去纠结神马是内建对象,神马是內建构造器.到后来你们便会发现其实她们都是对象. Array()是一个构建数组的內建构造器函数: var arr = new Array(); 与下面的是等效的: ...

  6. 程序新能优化-SQL优化

  7. atitit.身份认证解决方案attilax总结

    atitit.身份认证解决方案attilax总结 1.1. 身份认证1 1.2.  basic认证1 1.2.1. 编程实现basic客户端2 1.3. digest认证机制3 1.4. SSL认证3 ...

  8. flume 集群安装

    ./pssh -h ./host/all.txt -P mkdir /usr/local/app ./pssh -h ./host/all.txt -P tar zxf /usr/local/soft ...

  9. 利用Ajax增删改Sharepoint List Item

    在使用一个工具的是想要在本地的HTML文件或者JS,修改Sharepoint List中的数据. 如下是找到的方法.不知道还有其他方法没.IE中可以使用.记得加载Jquery. 如果是Chrome 浏 ...

  10. Android TextView走马灯效果

    布局: <TextView android:id="@+id/myTextView" android:layout_width="match_parent" ...