Java堆(年轻代 -- 老年代 -- 永久代)

JVM所管理的内存空间中,Java堆是最大的一块,主要用于存放各类实例对象,如下图:
在这里插入图片描述

JVM中的堆被划分为两个不同区域:新生代Young、老年代Old。新生代又划分为Eden(伊甸,标志新生), Survivor0(s0), Survivor(s1)。
JVM中堆的GC分为:Minor GC 和 Full GC(又称为Major GC)

年轻代
年轻代用于存放新创建的对象,存储大小默认为堆大小的1/15,特点是对象更替速度快,即短时间内产生大量的“死亡对象”
-Xmn 可以设置年轻代为固定大小
-XX:NewRatio 可以设置年轻代与老年代的大小比例
年轻代使用复制-清除算法和并行收集器进行垃圾回收,对年轻代的垃圾回收称为初级回收(minor GC)
minor GC 将年轻代分为三个区域,一个Eden, 两个大小相同的Survivor。应用程序只能同时使用一个Eden和一个活动Survivor, 另外一个Survivor为非活动Survivor(两个Survivor在活动与非活动间交替存在,即同一时刻只存在一个活动Survivor和一个非活动Survivor)。
当发生 minor GC时:JVM执行下述操作
1. 将程序挂起
2. 将Eden和活动Survivor中的存活对象(存活对象指的是仍被引用的对象)复制到另一个非活动的Survivor中(记录对象被复制到另一个Survivor的次数,在此称为年龄数,每次复制+1)
3. 清除Eden和活动Survivor中对象
4. 将非活动Survivor标记为活动,将原来的活动Survivor标记为非活动
上述即为一轮 minor GC 结束
如此往复多次 minor GC后,将多次被复制的对象(高龄对象)移动到老年代中
默认被移动到老年代的年龄为15,可以通过参数 -XX:MaxTenuring Threshold 来设置。
当然,对于一些占用较大内存的对象,会被直接送入老年代

老年代
老年代存储的是那些不会轻易“死掉”的对象,毕竟都在年轻代中熬出了头。
在老年代发生的GC成为 Full GC 。Full GC 不会像 Minor GC那么频繁
Full GC 采用 标记-清除算法 收集垃圾的时候会产生许多内存碎片(不连续的存储空间),因此此后若有较大的对象要进入老年代而无法找到适合的存储空间,就会提前触发一次GC收集,对内存空间进行整理

永久代
永久代(Perm Gen)是JDK7中的特性,JDK8后被取消。永久区是JVM方法区的实现方式之一,JDK8起,被元空间(与堆不相连的本地空间)取而代之
永久代存放的是应用元数据(应用中使用的类和方法),永久代中的对象在 Full GC 的时候进行垃圾回收

简单来讲,jvm的内存回收过程是这样的:
对象在Eden Space创建,当Eden Space满了的时候,gc就把所有在Eden Space中的对象扫描一次,把所有有效的对象复制到第一个Survivor Space,同时把无效的对象所占用的空间释放。当Eden Space再次变满了的时候,就启动移动程序把Eden Space中有效的对象复制到第二个Survivor Space,同时,也将第一个Survivor Space中的有效对象复制到第二个Survivor Space。如果填充到第二个Survivor Space中的有效对象被第一个Survivor Space或Eden Space中的对象引用,那么这些对象就是长期存在的,此时这些对象将被复制到Permanent Generation。

若垃圾收集器依据这种小幅度的调整收集不能腾出足够的空间,就会运行Full GC,此时jvm gc停止所有在堆中运行的线程并执行清除动作。
参考链接:http://www.cnblogs.com/snowwhite/p/9532311.html

猜你喜欢

转载自blog.csdn.net/weixin_43247186/article/details/87165480