JVM系列(6)-内存分配与回收策略

今天聊聊Java的内存分配和内存回收,内存的回收也就是前几节讲的垃圾回收,有兴趣的可以看下前面的文章,今天主要看下内存的分配。


先来回忆下Java运行时的数据区,如下图所示。Java对象所占的内存是在下面哪个区上分配的?,恭喜你答对了^_^。

JVM系列(6)-内存分配与回收策略_第1张图片

回忆点1:堆的内存布局


我们在讲垃圾收集算法的时候,有提到过分代收集算法(JVM系列(4)-垃圾收集算法)。也就是按对象的生存时间将其划分为新生代和老年代,不同的代,采用不同的垃圾收集算法。

新生代采用的是复制算法,老年代采用的是标记-清除算法或者标记整理。

在复制算法中,我们又讲到,按1:1的比例划分区间太浪费,因为利用率只有50%。有机构研究表明,我们可以按8:1的比例划分区间,Eden占8,两个Survivor各自占1。新生代的总可用空间为Eden(8) + Survivor(1) = 9。

综上,整个堆的内存布局如下所示。

JVM系列(6)-内存分配与回收策略_第2张图片

回忆点2:-Xms/-Xmx/-Xmn参数意思


-Xms:表示堆空间的最小大小

-Xmx:表示对空间的最大大小

-Xmn:表示新生代的大小

因为堆划分为新生代和老年代,所以老年代的大小 =(-Xmx) - (-Xmn);

例如:

-Xms20M表示堆最小为20M

-Xmx60M表示堆最大为60M

-Xmn15M表示新生代为15M

老年代最小为20M - 15M = 5M

老年代最大为60M - 15M = 45M


知识点1:什么是Minor GC和Full GC?


新生代GC就是Minor GC,也就是发生在新生代的垃圾收集动作;

特点是回收速度块。


老年代GC就是Full GC也称为Major GC,也就是发生在老年代的垃圾收集动作;

特点是回收速度慢,比Minor GC慢10倍以上。


知识点2:对象优先在Eden分配


Eden就是下面用红框标出的区域,当Eden没有足够的空间进行分配时,虚拟机会发起一次Minor GC。


JVM系列(6)-内存分配与回收策略_第3张图片

先来看个例子,设置VM参数:-verbose:gc -Xms20M -Xmx20M -Xmn10M

由设置的参数值,我们得到如下数据:

堆空间大小为20M

新生代大小为10M(Eden = 8M, Survivor = 1M, Survivor = 1M)

老年代大小为20M -10M = 10M

JVM系列(6)-内存分配与回收策略_第4张图片

对象优先在Eden上分配,在分配完c时,Eden已经占用了6M空间,还剩下2M空间,但是接下来d变量的大小是4M,剩余的2M不够分配了。所以此时呢,就会出发一次Minor GC。再延伸的讲点,因为GC时,a,b,c对象还都是存活的,按照复制算法的定义,a,b,c要被复制到Survivor区,但Survivor区大小只有1M,装不下。那怎么办呢?采用分配担保机制,将对象复制到老年代,老年代有10M大小,够用。


知识点3:大对象直接进入老年代


为什么要将大对象直接放入老年代?

我们知道GC是耗时的操作,新生代的GC频率又很频繁,如果把大对象分配到Eden区,就可能导致在还有很多空闲空间的时候,就得触发GC以大扫除足够的空间来安置它们。


用什么办法可以直接将大对象在老年代中分配呢?

可以通过-XX:PretenureSizeThreshold参数进行设置,大于设置值的对象,就会直接在老年代中分配。


注意:-XX:PretenureSizeThreshol只对Serial和ParNew两款收集器有效。


知识点4:长期存活的对象将进入老年代


我们知道堆空间分为年轻代和老年代,不同的代区采用的收集算法不同,如何能将不同的对象合理的放入不同的代区,以达到最好的回收效果,是我们追求的目标。


虚拟机中有个参数-XX:MaxTenuringThreshold表示在对象熬过多少次Minor GC后,就将其放入老年代。


这里面有个知识点是动态年龄判断,也就是并不是必须达到某个年龄之后,才进入老年代。如果在Survivor区中相同年龄的所有对象大小的总和大于Survivor区空间的一半,则年龄大于或者等于该年龄的对象可以直接进入老年代,而不需要等到-XX:MaxTenuringThreshold中要求的年龄。


知识点5:空间分配担保


我们知道年轻代采用的是复制算法,而复制算法,为了提供内存利用率,并没有按照1:1的比例分配内存,而是按照8:1或者其它值来设置。这样就可能遇到以下情况,Minor GC后,存活的对象还有很多,大小大于Survivor的空间,Survivor空间容纳不了,那怎么办?那就采用空间分配担保,将对象复制到老年代中,如果老年代剩余的空间也容纳不了,那就进行一次Full GC。


今天先到这儿,明天继续^_^。

JVM系列(6)-内存分配与回收策略_第5张图片


你可能感兴趣的:(JVM)