堆的结构是基于分代理论(垃圾回收)的,这种结构划分,是为了更好地进行垃圾回收。
我们将堆分为老年代、新生代。
永久代、元空间、堆这几个概念一直比较混乱。但是看到上图,堆的定义只包含 新生代 和 老年代。
这一点我们在实际设置 JVM 的参数的时候,你会发现,设置的空间的确只包含 新生代 和 老年代。
新生代 和 老年代 是根据对象的生命周期特点来区别的。
堆参数的设置
接下来,我们来看下 Java 8 中,关于 堆 参数的设置:
-Xms:表示堆的起始内存
-Xmx:表示堆的最大内存
一旦堆需要的空间大于 -Xmx 的值,就会抛出 Out Of Memory Error 异常。
一般情况下,将起始内存的值与最大值设置为相同值,避免重新分配空间,浪费时间。
可以看到,我在这里设置堆的起始大小和最大大小为 10M,最后的输出结果,可以看到 新生代 和 老年代,两者的和为 10M 左右。
最后的那个 元空间,并不在 堆的设置中。
我们注意到:新生代下面有三个分区,老年代下面只有一个分区。我们后面来介绍。
新生代结构
在新生代结构中,我们注意到分为了三个区域。这是为什么呢?
我们之前说过,新生代用来存放绝大多数新建的对象,这些对象绝大多数朝生夕灭。所以,一般采用 标记-复制 算法来进行处理。
之前介绍的 标记 - 复制 算法,是将内存区域分为 1:1,而这里,默认的分配为 8:1:1。
当然,这些比例是可以设置的。除此之外,还有个比较有趣的地方。
我们看上面的 eden 占用 2048 K,from 和 to 都占用 512 K,而显示的 新生代 总共占用了 2560 K。2560 = 2048 + 512,注意这里只加了一个 512 K。
等接下来,讲到对象的创建分配过程,就明白此处的原因了。
老年代结构
老年代的结构,只有一个结构,简简单单的。