文章目录
- @[toc]
- 1. 堆内存的分代
- 2. GC分类
- 3. 什么是GC
- 3.1 需要GC的内存区域
- 3.2 GC回收的对象
- 3.3 判断对象存活的两种算法
- 3.3.1 引用计数
- 3.3.2 可达性分析
- 3.4 什么时候触发GC
- 4. 常见的GC算法
- 4.1 标记-清除算法
- 4.2 复制算法
- 4.3 标记-压缩算法
文章目录
- @[toc]
- 1. 堆内存的分代
- 2. GC分类
- 3. 什么是GC
- 3.1 需要GC的内存区域
- 3.2 GC回收的对象
- 3.3 判断对象存活的两种算法
- 3.3.1 引用计数
- 3.3.2 可达性分析
- 3.4 什么时候触发GC
- 4. 常见的GC算法
- 4.1 标记-清除算法
- 4.2 复制算法
- 4.3 标记-压缩算法
1. 堆内存的分代
堆中内存分为新生代和老年代,其中新生代又分为Eden区、(Survivor)from区、(Survivor)To区
2. GC分类
新生代垃圾回收器:Minor GC/Young GC
老年代垃圾回收器:Mojor GC/Old GC
整理回收:Full GC(回收堆区和方法区)
3. 什么是GC
垃圾收集(Garbage Collection)通常被称为GC
在程序运行时,内存空间是有限的,那么如何及时的把不再使用的对象清除将内存释放出来,这就是GC要做的事情
3.1 需要GC的内存区域
JVM中,程序计数器、虚拟机栈、本地方法栈都是随线程而生随线程而灭,栈帧随着方法的进入和退出做入栈和出栈操作,实现了自动内存清理,因此内存垃圾回收主要集中于Java堆和方法区,程序运行期间,这部分内存的分配和使用都是动态的
3.2 GC回收的对象
当一个对象已经没有存活时,GC就会自动对其进行回收
判断对象是否存活有两种方法:引用计数和可达性分析
3.3 判断对象存活的两种算法
3.3.1 引用计数
每一个对象都有一个引用计数属性,新增一个引用时该属性 +1,引用释放时该属性 -1,当该属性为0时代表该对象可以被回收。
这种方法实现简单,缺点也很明显:需要额外的内存来计数、运行时需要维护计数器、无法解决循环引用的问题
3.3.2 可达性分析
-
基本思路
通过一系列被称为 “ GC Roots ” 的根对象作为起始节点集,从这些结点开始,通过引用关系向下搜索,搜索走过的路径被称为 “ 引用链 ”,如果某个对象到 GC Roots 没有任何引用链相连,就说明该对象不可达,即可被回收
如下图所示,对象4、5、6可被回收
要想理解可达性分析算法,就得想明白这几个问题:什么是对象可达、GC Roots 是什么、哪些对象可以作为 GC Roots
-
什么是对象可达
对象可达指的就是双方之间存在直接或间接的引用关系
-
GC Roots 是什么
GC Roots 就是 JVM 确定当前绝对不会被回收的对象,只要找到这种对象,此对象所依赖的其他对象肯定也不能被回收
-
哪些对象可被当作 GC Roots
-
方法区静态属性引用的对象
全局对象的一种,Class 对象本身很难被回收,只要 Class 对象不被回收,静态成员就不能被回收
-
方法区常量池引用的对象
也属于全局对象,常量本身初始化后不会改变,因此作为 GC Roots 也是合理的
-
被同步锁持有的对象
被 synchronized 锁住的对象是绝对不能回收的,GC 如果回收了对象,锁不就失效了嘛
-
3.4 什么时候触发GC
- 程序调用 System.gc 时触发
- 系统自身来决定GC触发的时机(根据Eden区和From Space区的内存大小来决定。当内存大小不足时,则会启动GC线程并停止应用线程)
GC又分为 minor GC 和 Full GC (也称为 Major GC )
Minor GC触发条件:当Eden区满时,触发Minor GC。
Full GC触发条件:
a.调用System.gc时,系统建议执行Full GC,但是不必然执行
b.老年代空间不足
c.方法去空间不足
d.通过Minor GC后进入老年代的平均大小大于老年代的可用内存
e.由Eden区、From Space区向To Space区复制时,对象大小大于To Space可用内存,则把该对象转存到老年代,且老年代的可用内存小于该对象大小
4. 常见的GC算法
4.1 标记-清除算法
该算法分为标记和清除两个阶段,标记就是把所有活动对象都做上标记的阶段,清除就是将没有做上标记的对象进行回收的阶段
4.2 复制算法
复制算法就是将内存空间按容量分成两块。当这一块内存用完时,就将存活着的对象复制到另一块上面,然后将已经使用过的一块一块清除掉
4.3 标记-压缩算法
标记-压缩算法与标记-清除算法类似,只是后续步骤是让所有存活的对象移动到一端,然后清除掉端边界以外的内存。