定义:
堆是JVM运行时内存区域中最大的一个区域,我们平常创建的对象,数组的内存都是在堆上分配的。
堆不仅仅只是一块大区域,它分为多个不同作用的区域。
- Old区。
- Young区。Young区又分为Eden区和两个大小相同的Survivor区,这两个区有的叫s1 和 s2 也有将from 区 和 to区。

解释:如图,左边的是old区,右边的是Young区。Young区又分为Eden区和Survivor区,Survivor区又分为大小相同的s1区和s2区。
Old区(老年代):
- old区一般都会存储着年龄比较大的对象,这里的年龄不是指存在时间,而是每一次young区的垃圾回收后,没有被回收掉的对象都会年龄加一,默认经过15次垃圾回收后没有被回收掉的对象,就会从young区进入到old区。
- 某个对象的大小超过某个阈值之后,会直接进入old区。
- old区是相对比较稳定的区域。
Young区(年轻代):
Young区分为两大块,一个是Survivor(s1 + s2),一块是Eden区,
Eden:s1: s2 = 8:1:1 。
Eden区:
正常创建对象分配内存的区域,大多数对象都是“朝生夕死”,就是大多数对象都会被垃圾回收掉。
Survivor区:
- Survivor区分为两块s1和s2。
- 在同一个时间点上,s1和s2只能有一个区有数据,另一个是空的。
为什么要区分出这些不同的区域呢,直接一个堆会怎么样:

如上图所示:蓝色的对象时要回收的对象,假如不只有一个堆,而不划分区间的话,进行一个回收之后,就会导致堆的内存空间不连续,零零散散,导致如果分配大的对象的话,会没有足够的连续空间来分配,又回导致gc启动,最终导致oom。
但是如果仅仅区分old区跟young区的话,也会出现上述问题。
所以就分配除了如上的内存模型划分。这个模型的好处如下:
- 首先一般正常对象创建都会在Eden区分配内存。当Eden区无法为对象分配足够内存时,就是触发Young GC。
- Young GC 会把Eden区和其中一个Survivor区(假如s1)的存活对象复制到另一个Survivor区(假如s2),然后把Eden区和s1区的所有对象清除掉。待得下次Young GC就会把s2 和 Eden区的对象复制到s1,然后再清空s2和Eden区。
- 以上第二点机制就是就可以保证内存空间连续,不会出现碎片现象,因为Eden区的数据每次都会被清空。但是会浪费其中一个Survivor区的空间,因为总有一个Survivor区是空的,用于待定,待复制。
假如Eden:s1:s2 = 8:1:1的话,就会意味着牺牲10%的Young区内存,换得GC后内存的连续性。 - 因为young区的对象大多数都是朝生夕死的,一般来说8:1:1是较为合理的,假如是6:2:2的话,就会浪费20%的young区内存,并且Eden区只有60%,这样会导致较为频繁的gc。

1349

被折叠的 条评论
为什么被折叠?



