GC算法

GC简介
一. 为什么要有GC策略原理?
a) 在工作和研究过程中不可避免的会遇到内存溢出与内存泄露的问题
二. GC解决了哪些问题
a) 那些对象可以被回收
b) 什么时候去回收这些对象
c) 采用什么样的方式回收
三. GC算法
a) 引用计数算法:引用计数归零时回收
i. 优点:效率高、
ii. 缺点:对循环引用的对象无法进行回收
b) 跟搜索算法 设立若干跟对象,当任何一个跟对象到某一个对象不可达时,则认为这个对象是可以清楚的

c) GC roots(GC根)在java语言中,可以当做GC roots的对象
i. 虚拟机栈中的引用对象 本地变量
ii. 方法区中的静态属性引用的对象
iii. 方法区中的常量引用的对象 final修饰的常量值
iv. 本地方法栈中JNI的引用对象 本地变量
d) 垃圾回收算法:
i. 标记清除法

  1. 当堆中的有效内存快要耗尽时,就会停止整个程序,然后进行标记和清除
  2. 标记:遍历所有的GC roots 然后将所有GC roots可达的对象标记为存活的对象
  3. 清除:将遍历堆中所有的对象全部清除掉
  4. 分析:
    a) 运行过程
    在这里插入图片描述

程序运行时的状态,他们的标志位都是0,如果内存耗尽就会发生下图
在这里插入图片描述
根据跟搜索算法 所有root对象可达的对象全部被标记为存活的对象,此时第一步标记就结束了
在这里插入图片描述
没有标记的对象就会被回收,而被标记的将会留下并且重新归0
唤醒停止的线程,让程序继续进行
b) 为什么要让线程中止?
如果未中止当标记结束之后此时程序New一个新的对象,则这个新创建的的对象就会被清除
c) 缺点:
i. 效率低 递归和全堆的遍历 在gc进行的时候要中止进程
ii. 清理出来的空闲内存是不连续的,为了解决这个问题JVM就不得不维持一个空闲的列表
ii. 复制算法:复制算法将内存划分为两个区间,在任意时间点,所有动态分配的对象只能在其中一个区间(活动区间),而另一个区间(空闲空间)则是空闲的

  1. 当活动区间内存耗尽时JVM将暂停程序运行,开启复制算法GC线程,接下来GC线程会将活动区间内的存货对象全部复制到空闲空间并且按照内存地址一次排列,与此同时,GC线程将更新存活对象的内存地址指向新的内存地址
  2. 空闲空间和活动区间交换了,垃圾对象现在全部留在原来的火工空间,也就是现在的空闲空间,事实上在空闲空间和活动空间交换时垃圾对象就一次被回收了
  3. 优缺点:
    a) 相比于标记清除算法,内存混乱的缺点
    b) 浪费一半的内存
    c) 假设对象存活率高 复制用的时间将特别长
    d) 在对象成活率低的时候 内存浪费太严重了
    iii. 标记整理法 标记+整理
  4. 标记: 遍历GC roots 将存活的对象标记
  5. 整理:移动所有存活的对象,且按照内存地址依次,最后将内存末端以后的地址清除
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

标记存活的对象将会被整理,按照内存地址一次排序,未被标记的清除,当我们需需要给新对象分配内存时,jvm只需要吃有一个内存的起始地址即可,这比维护一个空闲列表少了不少开销
3. 缺点:效率低 不但要标记存活的对象还有整理存活对象的地址
四. 三种算法的比较
a) 三个算法都是基于跟搜索算法去判断一个对象是否应该被回收
b) GC线程启用时都要暂停应用程序
c) 效率:
i. 内存整齐度:复制算法=标记整理法>标记清除法
ii. 内存利用率:标记整理法>标记清法>复制算法

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章