Java虚拟机-内存分配策略

Java技术体系中所提倡的自动内存管理策略最终可以归结为自动化地解决了两个问题:给对象分配内存以及回收分配给对象的内存;

几条普遍的分配规则:
1、对象优先在Eden区分配
年轻代分为三个区:1个Eden区+2个Survivor区。
大部分对象在Eden区中生成(大对象可以直接被创建在年老代),还存活的对象将被复制到一个Survivor区,当这个Survivor区满时,此区的存活对象将被复制到剩下的一个Survivor区中,当这个Survivor区也满了的时候,从第一个Survivor复制过来的并且此时还存活的对象,将被复制到年老区。
需要注意的是,Survivor的两个区是对称的,没先后关系,所以同一个区中可能同时存在从Eden区复制过来的对象和从前一个Survivor区复制过来的对象,而复制到年老区的就只有从第一个Survivor区过去的对象。并且Survivor区总有一个是空的。
Minor GC(Young GC)对象被创建时,内存的分配首先发生在年轻代,大部分的对象在创建后很快就不再使用,因此很快变得不可达,于是被年轻代的GC机制清理掉,这个GC机制被称为Minor GC或Young GC。
注意Minor GC并不代表年轻代内存不足,它事实上只表示在Eden区上的GC。
由于绝大部分对象都是短命的,甚至存活不到Survivor区中,所以Eden与Survivor的比例较大,HotSpot默认为8:1.

在Eden区,HotSpot虚拟机使用了两种技术来加快内存分配。分别是bump-the-pointer和TLAB(Thread- Local Allocation Buffers),这两种技术的做法分别是:由于Eden区是连续的,因此bump-the-pointer技术的核心就是跟踪最后创建的一个对象,在对象创建时,只需要检查最后一个对象后面是否有足够的内存即可,从而大大加快内存分配速度;而对于TLAB技术是对于多线程而言的,将Eden区分为若干段,每个线程使用独立的一段,避免相互影响。TLAB结合bump-the-pointer技术,将保证每个线程都使用Eden区的一段,并快速的分配内存;

2、大对象直接分配在老年代
所谓的大对象是指的需要大量连续内存空间的Java对象。比如:那种很长的字符串以及数组。
经常出现大对象容易导致内存还有不少空间时就提前触发垃圾收集以获取足够的连续空间来“安置”它们;
年老代存放从年轻代存活的对象。一般来说年老代存放的都是生命周期较长的对象。
年老代的空间一般比年轻代大,能存放更多的对象,在年老代上发生的GC次数也比年轻代少。
当年老代内存不足时,将执行Major GC,也叫Full GC;
可能存在年老代对象引用新生代对象的情况,如果需要执行Young GC,则可能需要查询整个老年代以确定是否可以清理回收,这显然是低效的。解决的方法是,年老代中维护一个512 byte的块——”card table“,所有老年代对象引用新生代对象的记录都记录在这里。Young GC时,只要查这里即可,不用再去查全部老年代,因此性能大大提高。
一般,老年代用的算法是标记-整理算法,即:标记出仍然存活的对象(存在引用的),将所有存活的对象向一端移动,以保证内存的连续;

在发生Minor GC时,虚拟机会检查每次晋升进入老年代的大小是否大于老年代的剩余空间大小,如果大于,则直接触发一次Full GC,否则,就查看是否设置了-XX:+HandlePromotionFailure(允许担保失败),如果允许,则只会进行MinorGC,此时可以容忍内存分配失败;如果不允许,则仍然进行Full GC(这代表着如果设置-XX:+Handle PromotionFailure,则触发MinorGC就会同时触发Full GC,哪怕老年代还有很多内存,所以,最好不要这样做)。
使用-XX:PretenureSizeThreshold参数,令大于这个设置值的对象直接在老年代分配;这样的目的主要是为了避免在Eden区以及2个Survivor区之间发生大量的内存复制;
-XX:PretenureSizeThreshold参数只对Serial 和ParNew 收集器有效,Parallel Sacvenge收集器不认识此参数。
-XX:PretenureSizeThreshold参数的值不能像-Xms一样直接写3M要写成3145728;

3、长时间存活的对象分配在老年代
虚拟机采用了分代收集的思想来管理内存,那么内存回收时就必须能识别哪些对象在新生代,哪些对象应在老年代,所以,虚拟机给每个对象定义了一个对象年龄计数器
如果对象在Eden区出生并经历一次Minor GC后仍然存活,并且能被Survivor区所容纳,那么对象年龄计数器值为1;
对象在Survivor区中每熬过一次Minor GC,年龄就会增加1;
默认年龄是15,可以通过设置-XX:MaxTenuringThreshold来设置。

4、动态对象年龄判定
为了能更好的适应不同程序的内存状况,虚拟机并不是永远都是要求对象的年龄达到了MaxTenuringThreshold才能晋升老年代;
如果在Survivor空间内相同年龄所有对象大小总和大于 Survivor空间的一半,年龄等于或大于该年龄的对象可以直接进入老年代,而无需达到MaxTenuringThreshold设定的年龄;

5、空间分配担保
在发生Minor GC之前,虚拟机会先检查老年代最大可用的连续空间是否大于新生代所有对象的总和。如果条件成立,那么Minor GC可以确保是安全的;
如果不成立,那么虚拟机会查看HandlerPromotionFailure设置值是否允许担保失败。
如果允许,会检查老年代最大可 用的连续空间是否大于历次晋升到老年代对象的平均大小,如果大于,则尝试进行一次Minor GC;如果小于,则会进行一次Full GC

转载于:https://www.cnblogs.com/time-info/p/4514190.html

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

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

相关文章

Source Insight常用的快捷键

From: http://blog.21ic.com/user1/4251/archives/2008/53650.html Source Insight常用的快捷键: Ctrl :Jump to definition Ctrl/ :Look up reference F3 : search backward F4 : search forward F5: go to Line F7 :Look up symbols F8 :Look up local symbols F…

ubuntu 安装fcitx输入法(3.6和4.0bate)

Ubuntu 10.10默认安装的输入法是ibus,在安装中文语言包(http://blog.csdn.net/wangjingfei/archive/2010/05/21/5614203.aspx)之后就可以使用。但是查看了一些网上的资料说是ibus有很多问题,例如会造成Linux QQ崩溃等。不知道是ibus的问题还是…

php在菜单栏里加子菜单,WordPress后台添加子菜单add_submenu_page()

接上文:WordPress后台添加顶级菜单add_menu_page(),今儿再分享一下在 wordpress 后台侧边栏添加子菜单的方法,用到的函数是:add_submenu_page()函数用法:add_submenu_page( $parent_slug, $page_title, $menu_title, $…

C#String详解

字符串:stringLength - 字符串的长度。 TrimStart() 压缩空格即消除字符串开始空格TrimEnd() 消除结尾空格Trim() 同时消除开头和结尾空格。注:中间空格不消除,因为英文单词之间用空格隔开。 ToUpper() 全部变大写ToLower() 全部变小写 Repl…

linux modprobe命令参数及用法详解--linux加载模块命令

From: http://www.linuxso.com/command/modprobe.html modprobe(module probe) 功能说明:自动处理可载入模块。 语  法:modprobe [-acdlrtvV][--help][模块文件][符号名称 符号值] 补充说明:modprobe可载入指定的个别模块,…

fedora下安装pps

fedora下安装pps成功,官方下载的deb包解压,然后手动安装。大致讲一下方法,如下:到官方下载deb包,右键解压后,进入解压的文件夹,将两个tar包解压,得到etc,opt,usr,三个文件夹&#xf…

ThinkPHP整合百度Ueditor图文教程

ThinkPHP整合百度Ueditor图文教程 ThinkPHP整合百度Ueditor,基于黄永成老师的视频说明的申明:最好大家都能写绝对路径的都写好绝对路径比如:window.UEDITOR_HOME_URL 他在教程里面已经说了的,我就不再次说了啊,就一笔…

php 支付加密,关于支付时rsa加密解密的函数

//加密function _checkPadding($padding, $type) {if ($type en) {switch ($padding) {case OPENSSL_PKCS1_PADDING :$ret true;break;default :$ret false;}} else {switch ($padding) {case OPENSSL_PKCS1_PADDING :case OPENSSL_NO_PADDING :$ret true;break;default :$…

电脑延迟关机命令Shutdown详解

From: http://www.ccw.com.cn/college/soft/b2c/os/htm2010/20101208_904968.shtml 目前实现自动关机的方法主要是使用第三方软件,比较麻烦!其实,Windows自身就具备自动关机功能,它是由系统内部的 "Shutdown.exe"升序来控制的,位于"C:/windows/System32"文…

树莓派Raspberry 操作GPIO--LED

一、 安装 wiringPi : sudo apt-get install wiringPi 二、查看安装版本 三、查看端口 四、创建源文件 touch myled.c 五、编写源代码 vi myled.c 使用cat myled.c 查看 六、编译和链接wiringPi库 七、运行

SQL逗号分隔的字段统计(摘自网络)

前言:由于很多业务表因为历史原因或者性能原因,都使用了违反第一范式的设计模式。即同一个列中存储了多个属性值(具体结构见下表)。这种模式下,应用常常需要将这个列依据分隔符进行分割,并得到列转行的结果…

缺少using namespace std;

错误现象&#xff1a; error C2143: syntax error : missing ; before < error C2501: list : missing storage-class or type specifiers error C2059: syntax error : < error C2039: iterator : is not a member of global namespace error C2238: unexpected token(s…

php json传输被过滤,php-the_content过滤器,用于将自定义字段添加到JSON响应

我对这个用于显示JSON API中的自定义字段的the_content过滤器感到绝望.我正在使用此插件http://wordpress.org/plugins/json-rest-api/从自定义帖子类型获得JSON响应.这些自定义帖子类型具有我必须在移动应用程序中显示的自定义字段.为了实现这一点,我编写了以下代码,该代码使用…

Ubuntu 和 Centos 的一点差别

1、 centos使用yum的方式&#xff0c;而Ubuntu使用apt-get 方式&#xff08;Raspberry也是&#xff09; 2、centos支持rpm包&#xff0c;但Ubuntu不支持 3、Ubuntu桌面系统比Centos好看&#xff0c;二者都有桌面系统和服务器系统 4、Ubuntu普通用户可以采用sudo执行root命令…

飞凌开发板 cramfs 镜像文件修改

From: http://blog.csdn.net/ex_net/article/details/7247111 CRAMFS文件系统是专门针对闪存设计的只读压缩的文件系统,其容量上限为256M,采用zlib压缩,文件系统类型可以是EXT2或EXT3.    如果使用RAMDISK方式来使用文件系统,那么在系统运行之后,首先得把flash上的映像文件全…