JVM探索之内存管理(三)
上节我们介绍了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探索之内存管理(三)的更多相关文章
- JVM探索之——内存管理(一)
本系列的第一篇文章,预计本系列最后面会有两三个案例. Java与C.C++不一样Java不需要Coder进行手动内存管理,而这一切都交给JVM进行自动内存管理,这从某种程度上来说也减轻了我们Coder ...
- JVM探索之——内存管理(二)
上篇文章我们介绍了JVM所管理的内存结构也就是运行时数据区(Run-Time Data Areas),现在我们将介绍JVM的内存分配与回收静态内存分配与动态内存分配 JVM的内存分配主要分为两种:静态 ...
- JVM介绍&自动内存管理机制
1.介绍JVM(Java Virtual Machine,Java虚拟机) JVM是Java Virtual Machine的缩写,通常成为java虚拟机,作为Java可以进行一次编写,到处执行(Wr ...
- Linux内存描述之内存区域zone--Linux内存管理(三)
1 内存管理域zone 为了支持NUMA模型,也即CPU对不同内存单元的访问时间可能不同,此时系统的物理内存被划分为几个节点(node), 一个node对应一个内存簇bank,即每个内存簇被认为是一个 ...
- Linux内存描述之内存区域zone–Linux内存管理(三)
服务器体系与共享存储器架构 日期 内核版本 架构 作者 GitHub CSDN 2016-06-14 Linux-4.7 X86 & arm gatieme LinuxDeviceDriver ...
- PHP内核探索:内存管理开篇
内存是计算机非常关键的部件之一,是暂时存储程序以及数据的空间,CPU只有有限的寄存器可以用于存储计算数据,而大部分的数据都是存储在内存中的,程序运行都是在内存中进行的.和CPU计算能力一样, 内存也是 ...
- COCOS学习笔记--Cocod2dx内存管理(三)-Coco2d-x内存执行原理
通过上两篇博客.我们对Cocos引用计数和Ref类.PoolManager类以及AutoreleasePool类已有所了解,那么接下来就通过举栗子来进一步看看Coco2d-x内存执行原理是如何的. / ...
- Java Core - JVM运行时内存管理
在读正文之前,阅读以下两篇博客学习并理解堆栈.作用域.本地方法的概念. 作用域:https://www.cnblogs.com/AlanLee/p/6627949.html 操作数栈:https:// ...
- jvm之自动内存管理
一.运行时数据区 程序计数器(线程私有) 1.程序计数器占用jvm内存较小,主要用来记录当前线程所执行的字节码的位置,因为jvm的多线程都是通过cpu对线程进行来回切换,所以在某个确定的时间cpu只会 ...
随机推荐
- input为disabled提交后得不到该值的解决方法
input的字段当为diabled时时无法获取数值得,所以最近不要用这个,我们可以用readonly带替代,即可解决这类问题 放在form表单中提交后得不到该值. 将disabled=”disable ...
- Hibernate总结(二)
在上一篇Hibernate总结(一)简单总结了一级缓存,快照,增删改查的简单使用,这一篇总结两张表的级联操作. 级联涉及到三种情况,many-many,1-many,many-1. 首先是1-many ...
- 矩阵乘法&矩阵快速幂&矩阵快速幂解决线性递推式
矩阵乘法,顾名思义矩阵与矩阵相乘, 两矩阵可相乘的前提:第一个矩阵的行与第二个矩阵的列相等 相乘原则: a b * A B = a*A+b*C a*c+b*D c d ...
- apache配置运行zendframework 2
其实ZF不用安装,只需引入就行,将ZF的library引入到项目的vendor\ZF2 就可以在ZF中开发了 在php版本5.4以上, 1 确保开启 extension=php_pdo.dllext ...
- GJM: Unity3D AssetBundle 手记 [转载]
这篇文章从AssetBundle的打包,使用,管理以及内存占用各个方面进行了比较全面的分析,对AssetBundle使用过程中的一些坑进行填补指引以及喷! AssetBundle是Unity推荐的 ...
- According to TLD or attribute directive in tag file, attribute end does not accept any expressions
问题描述: 在 JSP 页面中使用 JSTL 标签库,访问 JSP 页面时抛出了如下异常信息: org.apache.jasper.JasperException: /WEB-INF/manageUs ...
- IKONS – 赞!264 款手工打造的免费矢量图标
IKONS 是一套免费的矢量图标集,包含264款手工精心制作的可伸缩的矢量图标,分享给网页设计人员和开发人员.这些图标提供了 SVG.AI.ESP.PSD.CSH 和 PNG 格式.所有的图标都可以免 ...
- 微信浏览器或各种移动浏览器上:active伪类做的触觉反馈失效
在做移动端页面的时候,会发现PC上那种:hover的效果是不管用了的,但又要给用户一个点击反馈怎么办呢?我管它叫触觉反馈. 细心点就会发现浏览器有自带了一点触觉反馈,在点击a.button.input ...
- 【问题】js 改变鼠标样式,chrome浏览器不能立即更新,暂没有解决办法
元素的css,cursor可以改变鼠标样式.也就是鼠标放到元素上去时,改变为相应状态. 通过JS改变cursor时,我发现chrome浏览器不能立即更新,需要动一下鼠标才行,试了几个其它浏览器都是立即 ...
- 关于mapcontrol和pagelayoutcontrol切换时闪退
今天遇到一个很奇怪的的现象,在tabcontrol里切换到pagelayout时,程序会闪退,试了下之前的程序,没有问题,去网上搜了一下,也没人有这样的问题,然后就开始实验,添加一个控件,运行一次,最 ...