当前课程知识点:JAVA程序设计进阶 > 第六章 Java虚拟机 > 6.6 典型的垃圾收集算法 > Video
这一节我们将介绍
一些典型的垃圾收集的算法
我们首先看一下第一种算法
叫Mark-Sweep
也就是标记清除算法
那这种算法的话
思想是比较简单的
大家这个图
上面一张图就是我们可以
有三种标记
灰色的话是一种存活对象
绿色是未使用
那个黑色的话是可回收
我们对不同的内存块
都进行这个标记了以后
在当执行一次
这个垃圾回收过程当中
那就肯定把那些可回收的黑色的块
把它变成绿色
那也就是我们下面这张图的结果
那这种算法是一种最基础的
垃圾回收算法
那说到基础
是因为它比较容易实现
思想也比较简单
也就是做这个标记
就是两个阶段
第一个阶段是标记
第二阶段是这个清除
这种算法的话实现容易
这是它的优点
但是肯定有它的缺点
那就是它容易产生内存碎片
如果碎片太多的话会导致
后续过程当中
如果我们需要为大对象
来去分配内存的时候
你就不能找到足够大的空间
那这时候你又要去触发一次
这个垃圾收集的这个动作
那有没有一些改进的算法呢
这个肯定也是有的
那我们第二个算法叫复制算法
这个复制算法是这样
就是说我们看我们这张图的
上半部分
也是我们有做了标记的
有这个灰色的话是我们的存活对象
绿色是没使用的这个对象
黑色的话这个可回收的对象
那我们在回收的时候
还要做一些这个复制
尽量把一些空间给它衔接起来
使它变大
这个图的下半部分
就是我们一个回收后的一个结果
那作为这个复制算法的话
它的基本思想是这样的
它将我们的容量按容量
划分为大小相等的两块
每次它只使用其中的一块
当这一块的内存用完了
就将还存活着的对象
复制到另外一块上面
然后再把已经使用的内存空间
一次清理掉
这样一来就不容易出现
这种内存碎片的问题
这种算法实际上思想也比较简单
运行高效
而且它也有很大的优点
是不容易产生这个内存碎片
但是它这个对于内存空间的使用
做出了高昂的代价
它把原来能够使用的内存
缩减到原来的一半
另外的话
我们这个复制算法的效率
跟存活对象的数目多少
也有很大的关系
如果我们的存活对象很多
那我们的这个复制算法的效率
也会大大降低
那再往下第三个我们的算法
叫做标记整理算法
大家看这张图
上面图也是一样
说灰色是存活对象绿色为使用
黑色是这个可回收的
那当我们标记完了以后
在做整理以后
回收后的这个效果
是如下面这张图所看到的效果
大家可以看到这个还是不错的
这个它的大部分的内存
它都连在一起
那后面如果我们想做
大对象的分配的话
还是完全有可能的
那这种算法
它和这个上面前面那个
Mark-Sweep算法一样
就是它在完成标记以后
不是直接清理可回收对象
而是将存活对象
都向一端移动
然后清理掉端边界以外的内存
所以这是它的一个
这个很好的一个想法
刚才那个Mark-Sweep算法的话
它需要把内存的利用率只达到一半
那从内存的利用率上
肯定是比不上
我们这个标记整理算法的
第四个算法就叫做
分代收集的这个算法
这个算法是目前
大部分Java虚拟机的
垃圾收集器所采用的算法
那它的核心思想
是根据对象存活的生命周期
将内存划分成若干个不同的区域
一般情况下
它将堆区划分为老年代
就是Tenured Generation
和新生代Young Generation
那老年代的特点是
每次垃圾收集时只有少量对象
需要被回收
而新生代的特点
就是每次垃圾回收时
都有大量的对象需要被回收
那我们就可以根据
不同时代的特点
来去采取最适合的收集算法
目前大部分垃圾收集器
对于新生代的话
它都会采取copying算法
也就是复制算法
因为新生代中每次垃圾回收
都要回收大部分对象
也就是需要复制的操作次数较少
但是实际情况中并不是
按照1比1的比例
来划分这种新生代的空间的
一般说来是将新生代
划分为一块较大的Eden空间
也就是伊甸园空间
和两块较小的Survivor空间
也就是幸存者空间
每次的话
会使用伊甸园空间
和其中的一块Survivor空间
当进行回收时
将Eden和Survivor当中
还存活的对象
复制到另一块Survivor空间中
然后清理掉这个Eden
和刚才使用过的Survivor空间
对于这个老年代的这一部分
它每次回收
它只回收少量对象
所以我们一般使用的是
Mark-Compact算法
还需要提醒大家的是
对于这种分代搜集算法
在堆区之外还有一个代
就是永久代
叫Permanent Generation
它用来存储我们一些class
一些类常量方法描述等
对于永久代的回收
这个主要回收它的两部分内容
包括它的废弃常量和它的无用的类
那这些典型的垃圾回收的算法
我们就介绍这里
-1.0 导学
--Video
-1.1 线程的基本概念
--Video
-1.1 线程的基本概念--作业
-1.2 通过Thread类创建线程
--Video
-1.2 通过Thread类创建线程--作业
-1.3 线程的休眠
--Video
-1.3 线程的休眠--作业
-1.4 Thread类详解
--Video
-1.5 通过Runnable接口创建线程
--Video
-1.5 通过Runnable接口创建线程--作业
-1.6 线程内部的数据共享
--Video
-2.0 导学
--Video
-2.1 线程同步的思路
--Video
-2.2 线程同步的实现方式—Synchronization
--Video
-2.3 线程的等待与唤醒
--Video
-2.4 后台进程
--Video
-2.5 线程的生命周期与死锁
--Video
-2.6 线程的调度
--Video
-3.0 导学
--Video
-3.1 线程安全与线程兼容与对立
--Video
-3.2 线程的安全实现-互斥同步
--Video
-3.3 线程的安全实现-非阻塞同步
--Video
-3.4 线程的安全实现-无同步方案
--Video
-3.5 锁优化
--Video
-4.0 导学
--Video
-4.1 URL对象
--Video
-4.2 URLConnection对象
--Video
-4.3 Get请求与Post请求
--Video
-4.4 Socket通信原理
--Video
-4.5 Socket通信实现
--Video
-5.0 导学
--Video
-5.1 Socket 多客户端通信实现
--Video
-5.2 数据报通信
--Video
-5.3 使用数据报进行广播通信
--Video
-5.4 网络聊天程序
--Video
-6.0 导学
--Video
-6.1 Java虚拟机概念
--Video
-6.2 Java虚拟机内存划分
--Video
-6.3 Java虚拟机类加载机制
--Video
-6.4 判断对象是否存活算法及对象引用
--Video
-6.5 分代垃圾回收
--Video
-6.6 典型的垃圾收集算法
--Video
-6.7典型的垃圾收集器
--Video
-7.0 导学
--Video
-7.1 集合框架与ArrayList
--Video
-7.2 LinkedList
--Video
-7.3 HashMap与HashTable
--Video
-7.4 TreeMap与LinkedHashMap
--Video
-7.5 HashSet
--Video
-8.0 导学
--Video
-8.1 Java反射机制
--Video
-8.2 Java静态代理
--Video
-8.3 Java动态代理
--Video
-8.4 Java 反射扩展-jvm加载类原理
--Video
-8.5 Java进阶课程总结
--Video