JAVA分代收集机制详解

Java堆中是JVM管理的最大一块内存空间。主要存放对象实例。
在JAVA中堆被分为两块区域:新生代(young)、老年代(old)。
堆大小=新生代+老年代;(新生代占堆空间的1/3、老年代占堆空间2/3)
新生代又被分为了eden、from survivor、to survivor(8:1:1);
新生代这样划分是为了更好的管理堆内存中的对象,方便GC算法---复制算法来进行垃圾回收。
JVM每次只会使用eden和其中一块survivor来为对象服务,所以无论什么时候,都会有一块survivor空间,因此新生代实际可用空间只有90%。
新生代GC(minor gc)----------指发生在新生代的垃圾回收动作,因为JAVA对象大多数都是朝生夕死的特性,所以minor gc非常平凡,使用复制算法快速的回收。
新生代几乎是所有JAVA对象出生的地方,JAVA对象申请的内存和存放都是在这个地方。
当对象在eden(其中包括一个survivor,假如是from),当此对象经过一次minor gc后仍然存活,并且能够被另外一块survivor所容纳(这里survivor则是to了),则使用复制算法将这些仍然存活的对象复制到to survior区域中,然后清理掉eden和from survivor区域,并将这些存活的对象年龄+1,以后对象在survivor中每熬过一次gc则增加1,当年龄达到某个值时(默认15,通过设置参数-xx:maxtenuringThreshold来设置),这些对象就会成为老年代!
但是也不一定,当一些较大的对象(需要分配连续的内存空间)则直接进入老年代。
老年代GC(major gc)----------指发生在老年代的垃圾回收动作,所采用是的标记--整理算法。
老年代几乎都是经过survivor熬过来的,它们是不会那么容易“死掉”,因此major gc不会想minor gc那样频繁。

JVM 新生代为何需要两个 Survivor 空间?

我们知道,目前主流的虚拟机实现都采用了分代收集的思想,把整个堆区划分为新生代和老年代;新生代又被划分成 Eden 空间、 From Survivor 和 To Survivor 三块区域。 

看书的时候有个疑问,为什么非得是两个 Survivor 空间呢?要回答这个问题,其实等价于:为什么不是0个或1个 Survivor 空间?为什么2个 Survivor 空间可以达到要求? 

为什么不是0个 Survivor 空间? 

这个问题等价于:为什么需要 Survivor 空间。我们看看如果没有 Survivor 空间的话,垃圾收集将会怎样进行:一遍新生代 gc 过后,不管三七二十一,活着的对象全部进入老年代,即便它在接下来的几次 gc 过程中极有可能被回收掉。这样的话老年代很快被填满, Full GC 的频率大大增加。我们知道,老年代一般都会被规划成比新生代大很多,对它进行垃圾收集会消耗比较长的时间;如果收集的频率又很快的话,那就更糟糕了。基于这种考虑,虚拟机引进了“幸存区”的概念:如果对象在某次新生代 gc 之后任然存活,让它暂时进入幸存区;以后每熬过一次 gc ,让对象的年龄+1,直到其年龄达到某个设定的值(比如15岁), JVM 认为它很有可能是个“老不死的”对象,再呆在幸存区没有必要(而且老是在两个幸存区之间反复地复制也需要消耗资源),才会把它转移到老年代。 

总之,设置 Survivor 空间的目的是让那些中等寿命的对象尽量在 Minor GC 时被干掉,最终在总体上减少虚拟机的垃圾收集过程对用户程序的影响。 

为什么不是1个 Survivor 空间? 

回答这个问题有一个前提,就是新生代一般都采用复制算法进行垃圾收集。原始的复制算法是把一块内存一分为二, gc 时把存活的对象(Eden和Survivor to)从一块空间(From space)复制到另外一块空间(To space),再把原先的那块内存(From space)清理干净,最后调换 From space 和 To space 的逻辑角色(这样下一次 gc 的时候还可以按这样的方式进行)。 

我们知道,在 HotSpot 虚拟机里, Eden 空间和 Survivor 空间默认的比例是 8:1 。我们来看看在只有一个 Survivor 空间的情况下,这个 8:1 会有什么问题。此处为了方便说明,我们假设新生代一共为 9 MB 。对象优先在 Eden 区分配,当 Eden 空间满 8 MB 时,触发第一次 Minor GC 。比如说有 0.5 MB 的对象存活,那这 0.5 MB 的对象将由 Eden 区向 Survivor 区复制。这次 Minor GC 过后, Eden 区被清理干净, Survivor 区被占用了 0.5 MB ,还剩 0.5 MB 。到这里一切都很美好,但问题马上就来了:从现在开始所有对象将会在这剩下的 0.5 MB 的空间上被分配,很快就会发现空间不足,于是只好触发下一次 Minor GC 。可以看出在这种情况下,当 Survivor 空间作为对象“出生地”的时候,很容易触发 Minor GC ,这种 8:1 的不对称分配不但没能在总体上降低 Minor GC 的频率,还会把 gc 的时间间隔搞得很不平均。把 Eden : Survivor 设成 1 : 1 也一样,每当对象总大小满 5 MB 的时候都必须触发一次 Minor GC ,唯一的变化是 gc 的时间间隔相对平均了。 

上面的论述都是以“新生代使用复制算法”这个既定事实作为前提来讨论的。如果不是这样,比如说新生代采用“标记-清除”或者“标记-整理”算法来实现幸存对象的移动,好像确实是只需要一个 Survivor 就够了。至于主流的虚拟机实现为什么不考虑采用这种方式,我也不是很清楚,或许有实现难度、内存碎片或者执行效率方面的考虑吧。 

为什么2个 Survivor 空间可以达到要求? 

问题很清楚了,无论 Eden 和 Survivor 的比例怎么设置,在只有一个 Survivor 的情况下,总体上看在新生代空间满一半的时候就会触发一次 Minor GC 。那有没有提升的空间呢?比如说永远在新生代空间满 80% 的时候才触发 Minor GC ? 

事实上是可以做到的:我们可以设两个 Survivor 空间( From Survivor 和 To Survivor )。比如,我们把 Eden : From Survivor : To Survivor 空间大小设成 8 : 1 : 1 ,对象总是在 Eden 区出生, From Survivor 保存当前的幸存对象, To Survivor 为空。一次 gc 发生后: 
1)Eden 区活着的对象 + From Survivor 存储的对象被复制到 To Survivor ; 
2) 清空 Eden 和 From Survivor ; 
3) 颠倒 From Survivor 和 To Survivor 的逻辑关系: From 变 To , To 变 From 。 

可以看出,只有在 Eden 空间快满的时候才会触发 Minor GC 。而 Eden 空间占新生代的绝大部分,所以 Minor GC 的频率得以降低。当然,使用两个 Survivor 这种方式我们也付出了一定的代价,如 10% 的空间浪费、复制对象的开销等。

jvm
分类: JVM

转载于:https://www.cnblogs.com/xifenglou/p/9087480.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/353623.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

FizzBu​​zz Kata与Java流

在柔道练习仅几周之后,我的儿子感到无聊。 他抱怨说自己没有学任何东西,因为他一遍又一遍地做着同样的事情。 混淆学习和做新事物的不仅仅是幼儿。 例如,有多少软件开发人员通过执行kata或参加dojos来进行刻意练习的麻烦? 重复您…

高可用架构

转载于:https://www.cnblogs.com/138026310/p/9088341.html

vc6.0快捷键

2010-09-14 17:46 F1 显示帮助,如果光标停在代码的某个字符上,显示MSDN中相应的帮助内容(需要安装MSDN才能使用) F2 书签功能: CtrlF2 --在某行设置一个书签(再按一次是取消) F2 --跳到下一个书签位置 ShiftF2 --跳到上一个书签位置 CtrlShiftF2 --删除…

ES6 各浏览器支持情况

http://kangax.github.io/compat-table/es6/转载于:https://www.cnblogs.com/likwin/p/9091008.html

MFC删除类的小窍门

VC 并没有提供删除一个类的简洁方法,我们需要手工删除,但过程并不复杂。例如,我们有一个 CMyButton 的类,对应的文件为 MyButton.h 和 MyButton.cpp ,我们先到工程目录中删除这两个文件,此时该类信息自动从…

ios plist 国际化_Java与iOS对话:Java对象与Apple plist序列化

ios plist 国际化我很高兴地宣布我的第一个开源项目java-plist-serializer可以帮助您将Java(尤其是基于Spring的应用程序)与iOS应用程序集成在一起。 背景 我正在将Java webapp作为后端并且客户端是iOS设备的项目。 最近,我收到了创建Web服务…

vtk环境搭建(windowsXP/win7,vtk6.0.0+cmake2.8+vs2010)

1. 安装vs2010(默认方式) 2. 安装cmake2.8(默认方式) 3. 新建文件夹作为vtk文件根目录(例如"E:\vtk6.0"),解压vtk-6.0.0.zip到根目录,将VTK6.0.0改名为vtk;解…

P1993 小K的农场 (差分约束)

题目描述 小K在MC里面建立很多很多的农场,总共n个,以至于他自己都忘记了每个农场中种植作物的具体数量了,他只记得一些含糊的信息(共m个),以下列三种形式描述: 农场a比农场b至少多种植了c个单位…

将Quartz与Spring集成

在Java应用程序中调度作业时,Quartz是第一个考虑的工具。 Quartz是由最流行的RDBMS支持的作业调度程序。 这真的很方便,并且很容易与spring集成。 为了创建石英模式,您必须下载石英发行版并解压缩位于crystal-2.2.3 / docs / dbTables /中的…

linux下md5sum的使用

在linux或Unix上,md5sum是用来计算和校验文件报文摘要的工具程序。一般来说,安装了Linux后,就会有md5sum这个工具,直接在命令行终端直接运行。1、使用md5sum来产生指纹(报文摘要)命令如下:md5su…

深入理解Python中的元类(metaclass)

注:本文原稿来自stackoverflow,原文链接,目前已收获5k高赞。 一、类也是对象 在理解元类之前,你需要先掌握Python中的类。Python中类的概念借鉴于Smalltalk,这显得有些奇特。在大多数编程语言中,类就是一组…

6个步骤卸载wine

今天在ubuntu下装了个wine,感觉界面很难看,跟ubuntu风格不协调。所以我把它卸载了。 根据网上找的资料,我是按如下步骤卸载: 1.终端运行sudo apt-get remove wine,运行发现系统还有wine的图标残留,于是 2…

OpenStack基础知识-virtualenv工具详解

1、virtualenv介绍 virtualenv通过创建一个单独的虚拟化python运行环境,将我们所需的依赖安装进去,不同项目之间相互不干扰,从而解决不同的项目之间依赖不同,造成的冲突问题 2、安装virtualenv 通过pip命令,安装virtua…

java中的五种排序方法_用Java排序的五种有用方法

java中的五种排序方法Java排序快速概述: 正常的列表: private static List VEGETABLES Arrays.asList("apple", "cocumbers", "blackberry");Collections.sort(VEGETABLES);output: apple, blackberry, cocumbers反向排…

压缩vmware中的ubuntu系统(虚拟机瘦身大法)

压缩vmware中的ubuntu系统&#xff08;虚拟机瘦身大法&#xff09; 前提:你的虚拟机大小 < 你放置虚拟机的磁盘的剩余空间 1.在Termial(终端)里 运行"sudo vmware-toolbox"(需要root权限) 2.选择“shrink”选项卡 3.选中“/”&#xff0c;点击“shrink”按钮 4.完…

P2619 [国家集训队2]Tree I

P2619 [国家集训队2]Tree I 链接 分析&#xff1a; 为了确定白边选入的数量&#xff0c;所以给白边加一个权值&#xff0c;二分这个值&#xff0c;然后最小生成树。可以发现白边的数量虽这个值的增大而减小&#xff0c;满足单调性。 有一个问题&#xff1a;如果在二分过程中给白…

程序化JCMD访问

在线提出的问题表明&#xff0c;开发人员偶尔希望通过其Java应用程序访问通常从针对该应用程序外部运行JConsole &#xff0c; VisualVM或JDK命令行工具获得的信息类型。 以下是这类问题的一些示例&#xff1a; 如何以编程方式获取jmap直方图&#xff1f; 以编程方式从Java应…

Ubuntu瘦身与扩容运动

Ubuntu瘦身与扩容运动 2009-11-26 18:18:24| 分类&#xff1a; 计算机 | 标签&#xff1a; |字号大中小 订阅 Ubuntu瘦身与扩容运动 2009年08月14日 星期五 12:25大家都知道系统用久了就会慢慢变得臃肿,速度当然也就会有一些影响,所以当那些加速系统的方法不在奏效的时候…

认识jQuery

一、JavaScript库 把一些浏览器兼容性的代码或者需要常用的函数装在一个js文件里,封装了很多js代码的一个js文件就是一个库 二、jQuery 是一个JavaScript库&#xff0c;免费开源的&#xff0c;体积小&#xff0c;链式编程&#xff0c;隐式迭代&#xff0c;很多优点jQuery 的功能…

Axis2 WebService(配置、发布、调用)

from:http://www.lifeba.org/arch/java_axis2_webservice.html 准备工作 1、下载&#xff1a;axis2-1.5.4-bin.zip,axis2-1.5.4-war.zip 下载地址&#xff1a;http://axis.apache.org/axis2/java/core/ 2、环境变量设置 AXIS2_HOME E:\research\axis2-1.5.4-bin\axis2-1.5.4 J…