深入理解java虚拟机(第二版)——第三章:内存分配与回收策略

一、java对象分配策略

java中所说的自动内存管理最终可以归结到两个问题:

  • 自动分配不存
  • 自动回收内存
    对象的内存分配主要是在堆上进行,堆根据对象不同的存活周期分为不同的区域,新生对象一般分在了Eden区域,如果启动了线程分配缓冲,则优先会分配到TLAB上。有少数情况新生对象会直接分配到老年代区域。实际情况要根据虚拟机模式和收集器组合来确定。
    以下结论是Client模式下配合Serial和Serial Old收集器。

1、对象优先分配在Eden区域

在多数情况下,对象优先分配在Eden区域,当Eden区域的没有足够的内存分配时,虚拟机将发生一次minor GC。
以下代码测试新生对象的分配机制。设置堆大小为20M,不可扩展,新生代大小为10M,老年代10M,Eden和from survivor和to survivor的比例为8:1:1。

public class TestAllocation {
    private static final int _1MB = 1024;
    //VM参数 -verbose:gc -Xms20M -Xmx20M -Xmn10M -XX:+PrintGCDetails -XX:SurvivorRatio=8
    public static void testAllocation(){
        byte[] allocation1, allocation2, allocation3, allocation4;
        allocation1 = new byte[2 * _1MB];
        allocation2 = new byte[2 * _1MB];
        allocation3 = new byte[2 * _1MB];
        allocation4 = new byte[4 * _1MB];
    }
    public static void main(String[] args) {
        testAllocation();
    }
}

在进行allocation1 ,allocation12, allocation13时对象正常分配到Eden区,在分配第四个对象的时候发现Eden的空间不够用,触发一次Minor GC,minor GC过后对象1,2,3正常情况下应该被复制算法复制到另一块survivor空间,但是由于survivor空间不够所以通过分配担保将123转移到了老年代空间中,此时Eden和两块survivor空闲,老年代空间占用6MB。最后第四个对象成功分配到Eden空间。
(在java8中运行上述代码,没有出现相同的结果。。。。。)

2、大对象直接进入老年代

大对象的存储需要大量的连续的内存空间,这对虚拟机的内存管理来说不是一个好消息。虚拟机设置了-XX:PretenureSizeThreshold做标志,当新生对象大小超过了-XX:PretenureSizeThreshold设置的大小则独享直接分配在老年代中。这样做的好处是避免了在新生代中大量的复制(新生代采用的是复制算法)。坏处是增加了老年代的垃圾收集任务。且老年代的垃圾收集速度要比新生代耗时长很多。

3、长期存活的对象进入老年代

虚拟机为每一个对象定义了一个对象年龄计数器,如果在出生在Eden经过一个Minor GC后存活且被survivor容纳,则age设为1。对象在survivor每熬过一次Minor GC则age加1,当age增加到15时晋升到老年代中。晋升age可以调节,参数为-XX:MaxTenuringThreshold。
  虚拟机并不是永远要求对象的年龄达到-XX:MaxTenuringThreshold之后才能晋升到老年代。如果在Survivor空间的相同年龄所有对象大小的总和超过了Survivor空间的一半,则虚拟机就允许大于或等于该年龄的对象直接进入老年代。

二、 其他概念总结

1、GC分类

GC按照发生位置分为Minor GC和Major GC:

  • Minor GC:发生在新生代。由于新生代对象的特点,Minor GC发生较频繁,速度也很快。
  • Major GC/Full GC:发生在老年代。Major GC一般会伴随多次的Minor GC,速度也较Minor GC慢出一个数量级。

2、空间分配担保

在新生代中使用的收集算法是复制算法,一般将新生代分成三个区域,Eden区,from Survivor和to Survivor,这三个区域的比大小例是8:1:1。一半新生对象没有特殊设置的话会直接出生在Eden区域,如果Eden区域空间不够则会发生一次Minor GC。如果在Minor GC时Survivor空间不够这就需要分配担保。
分配担保就是Minor GC过程中Survivor区域不足以容纳Eden区的存活对象从而向老年代借一块区域用于存放存活对象。
老年代在执行分配担保时会有一些执行机制。
1、在Minor GC前虚拟机会检查老年代的最大可用连续空间是否大于新生代所有对象总空间,如果大于,则分配担保安全。
2、如果老年代最大连续总空间小于新生代所有对象之和。虚拟机检查HandlePromotionFailure设置是否允许分配担保失败,如果允许。继续检查老年代最大连续空间是否大于历次晋升到老年代对象的平均大小。如果大于,虚拟机将允许发生Minor GC,如果小于,HandlePromotionFailure设置为不允许,此时需要进行一次Full GC。
(JDK 6 Update 24之后的规则变为只要老年代的连续空间大于新生代对象总大小或者历次晋升的平均大小就会进行Minor GC,否则将进行Full GC。)

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,884评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,347评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,435评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,509评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,611评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,837评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,987评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,730评论 0 267
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,194评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,525评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,664评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,334评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,944评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,764评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,997评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,389评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,554评论 2 349

推荐阅读更多精彩内容