java中垃圾回收的原理(Java垃圾回收)
java中垃圾回收的原理(Java垃圾回收)优点:简单高效问题:内存缩小一半,代价太高;如果对象的存活率很高,就不实用三种算法比较可达性分析(解决循环依赖问题)从GC根节点开始向下搜索,搜索走过的路径称为引用链。当一个对象到GC根节点没有任何引用链相连时则证明此对象是不可用的不可达对象。将可用的内存按照容量分为大小相等的两块,每次只使用其中的一块,这一块内存用完时就将还存活的对象复制到另一块上面去,然后把已经用过的内存空间一次清理掉(如此循环往复)。
垃圾回收机制主要是对内存的释放,因为java在创建对象时需要申请一个内存空间。
- 不再使用的内存空间应回收;
- Java消除了程序员回收无用内存空间的职责,提供了一种系统级别线程跟踪存储空间分配情况,在JVM空闲时,检查并释放可以被释放的存储空间;
- 垃圾回收在java程序运行中自动进行,程序员无法精确控制干预;
- 垃圾回收自动处理提高了内存空间的使用效率,也提高了变成人员的利用效率,减少了因为没有释放空间而导致的内存泄露。
- 自动GC:一般在JVM内存不足时由JVM系统自动对内存进行垃圾回收。
- 手动GC:手动对内存进行分配和释放,如果忘记释放,对应的内存不能被再次使用。
System.gc(); //提醒JVM的垃圾回收执行GC操作,但是不确定是否马上执行GC。
垃圾回收的判断策略引用计数
每个对象都有一个引用计数属性,新增一个引用时,计数加一,引用释放时,计数减一,引用计数为0时可以回收,此方法简单,无法解决循环依赖问题。
- 绿色云朵是内存中的根对象,表示程序中正在使用的对象
- 蓝色圆圈是内存中的活动对象,其中的数字表示其引用计数
- 灰色圆圈是内存中没有活动对象引用的对象,表示非活动对象
- 红色对象指实际上应用程序使用不到的垃圾对象但由于引用计数的限制,仍然存在内存泄漏
可达性分析(解决循环依赖问题)
从GC根节点开始向下搜索,搜索走过的路径称为引用链。当一个对象到GC根节点没有任何引用链相连时则证明此对象是不可用的不可达对象。
- 复制算法
将可用的内存按照容量分为大小相等的两块,每次只使用其中的一块,这一块内存用完时就将还存活的对象复制到另一块上面去,然后把已经用过的内存空间一次清理掉(如此循环往复)。
- 标记清除算法
- 标记阶段:从根节点开始标记所有的可达对象,未被标记的为垃圾对象。
- 清除阶段:清除所有未被标记的对象。
- 标记整理算法
- 标记阶段:从根节点开始标记所有的可达对象,未被标记的为垃圾对象。
- 整理阶段:将所有存活的对象压缩到内存的一端,之后清理边界外的所有空间。
三种算法比较
- 复制算法
优点:简单高效
问题:内存缩小一半,代价太高;如果对象的存活率很高,就不实用
- 标记清楚算法
优点:速度较快
问题:容易产生内存碎片(主要原因:内存空间不连续)
- 标记整理算法
优点:没有内存碎片
问题:效率不高
JVM用的是可达性分析作为GC判断策略。
JVM采用分代垃圾收集:
新生代
- 复制算法
新生代 | |
区域 |
启用复制算法次数 |
伊甸园区 |
1 |
存活区 |
默认15次 |
老生代
- 标记清除算法
- 标记整理算法
关于新生代与老生代的理解
一般情况下新建的对象均会被分配到伊甸园区(一些大对象特殊处理)这些对象经过第一次gc后,如果仍然存活将会被迁移到存活区,大对象直接进入老生代(大对象指的是需要大量连续内存空间的对象),这样做的目的是避免在伊甸园区和两个存活区之间发生大量的内存拷贝。