垃圾分类,从我做起-----论JVM的自我修养
GC根本目的:从内存中剔除死掉的对象。
判断一个对象是否死亡主要有两种方式:
可达性分析:从GC Roots开始向下搜索,搜索所走过的路径为引用链。当一个对象到GC roots没有任何引用链相连时,则证明此对象不可用,为不可达对象。
引用计数: 每个对象有一个引用计数属性,新增一个引用时计数加1,引用释放时计数减1,计数为0时可以回收。此方法简单,无法解决对象相互循环引用的问题。
GC Roots包括:
虚拟机栈中引用的对象。
方法区中类静态属性实体引用的对象。
方法区中常量引用的对象。
本地方法栈中JNI引用的对象。
JVM 堆内存划分:
新生代(Young Generation
):新对象和没达到一定年龄的对象都在新生代。由 伊甸园 存活区 伸缩区组成,
老年代(Old Generation
):被长时间使用的对象在老年代。由 老年区 伸缩区组成
元空间(Meta Space
):由 元空间 伸缩区组成
GC过程:
-
新对象产生,为该对象进行内存空间的申请。
-
判断 伊甸园区 是否有内存空间,如果此时有充足内存空间,则直接将新对象保存到伊甸园区。
-
如果 伊甸园区 内存空间不足, 执行Minor GC操作,清理Eden 不活跃对象。继续判断 伊甸园区 空间是否充足?如果充足,则将新的对象直接在伊甸园区进行内存空间分配。
-
如果 伊甸园区 空间依然不足,判断 存活区 有无剩余空间,有则将伊甸园区的部分活跃对象保存在存活区,继续判断 伊甸园区 内存空间是否充足,如果充足,则进行内存空间分配。
-
如果 存活区也 没有内存空间了,判断老年区是否空间充足,是则将存活区中的活跃对象保存到老年区,将伊甸园区将部分活跃对象保存地存活区中,再在伊甸园区为新对象分配内存空间。
-
如果 老年代也 没有存储空间了,那么Major GC(Full GC)。然后再将存活区中的活跃对象保存到老年区,再将伊甸园区的部分活跃对象保存到存活区,最后在伊甸园区为新对象分配内存空间。
-
如果 执行Full GC之后,依然空间依然不足,会产生OOM(OutOfMemoryError)异常
垃圾回收算法:
- 标记/清除
- 复制
- 标记/整理
新生代采用的是“复制”算法 ,老年代采用的是“标记/清除” 或者 “标记/整理”。
垃圾收集器:
新生代收集器:
- Serial:单线程,主要是给Client模式下的JVM用
- ParNew:支持多线程
- Parallel Scavenge: 采用复制算法,支持多线程
老年代收集器:
- Serial Old:采用 标记/整理 算法 ,单线程,主要是给Client模式下的JVM用
- Parallel Old: 采用 标记/整理算法 ,支持多线程
- CMS(Concurrent Mark Sweep):采用 标记/清除算法 ,支持并发