GC回收与算法

在运行程序中没有任何指针指向的对象称为垃圾

标记阶段:发现垃圾

  • 引用计数算法:
    • 对象自身开启空间记录被引用次数
    • 缺点是无法解决循环引用问题
    • python中使用此算法,通过手动解除引用和采用弱引用来解决循环信用问题
  • 可达性分析算法:
    • 从gc root开始,在引用链上的对象是可达的,否则不是可达,可以被回收
    • 缺点是效率低会存在STW,原因是必须保证在一个保证一致性的内存快照中进行,此时需要暂停用户线程
    • GC Root有哪些?
      • 虚拟机栈中引用的对象
      • 本地方法栈中引用的对象
      • 方法区中类静态属性引用的对象
      • 方法区中常量池中的引用
      • 所有被同步锁持有的对象
      • 虚拟机内部的引用:基本数据类型对应的类对象,异常对象,系统类加载器
      • 分代回收的影响:例如只收集年轻代时,老年代中的对象对新生代有引用时也可以作为根节点
    • 如何查看GC Root:通过工具MAT
    • 如何进行对象引用的溯源#通过工具JProfiler

对象的finalization机制

在对一个对象进行垃圾回收之前虚拟机会去调用对象的finalize方法

  1. 用于释放资源:关闭文件,套接字,数据库连接等
  2. 不建议主动调用:有可能导致对象复活或执行性能差
  3. 由于finalize的存在对象会有三种状态:可触达,可复活(还未执行finalize),不可触及(已经执行finalize)

清除阶段:处理垃圾

标记清除算法

  • 从根节点标记可达对象(非垃圾对象),标记过程产生STW,是否存活标记放在对象头中,对未被标记对象进行清除
  • 缺点是什么?
    • 效率不高,两次遍历,第一次是可达分析,第二次是全量遍历回收
    • 会产生STW
    • 会产生空间碎片,并需要维护空闲列表
  • 如何清除?
    • 并不是真的置空,而是将地址维护到空闲列表

复制算法

  • 对内存区域进行分区,每次将存活对象从回收区复制到另一个区域,例如年轻代的回收机制
  • 优点
    • 执行高效
    • 内存空间连续
  • 缺点
    • 浪费内存,需要两倍内存空间
    • 适合存活对象少的年轻代

标记整理算法

  • 标记存活对象然后让所有存活的对象都向一端移动,直接清理掉端边界以外的内存。适合年老代。注意其不需要维护空闲列表,直接清除垃圾对象
  • 优点
    • 没有内存碎片化问题
    • 不用占用两倍内存空间
  • 缺点
    • 效率相对低于复制算法
    • 移动对象时如果对象被其它对象引用,要整体调整引用地址
    • 需要STW

分代回收算法

不同年龄代的对象采用不同的回收算法。
新生代对象存活率低,就采用复制算法;
老年代存活率高,就用标记清除算法或者标记整理算法

增量收集算法

每次垃圾收集线程只收集一部分区域,接着切换到应用线程,以此往复,直到垃圾收集完成。
底层依然是标记清除和复制算法。

优点:减少STW
缺点:频繁线程切换导致系统吞吐量降低

分区收集算法

把一块大的内存空间划分为若干区域的小空间,每一个小空间的分代年龄不同(新生代,老年代,永久代,大对象),每次只对需要收集的部分区域进行收集。

垃圾回收的基本概念

  • system.gc()手动触发full gc,但是不能保证能够被立即执行。一般用不到。
  • 内存溢出oom:没有空闲内存可用,垃圾收集后也无法提供足够空间
  • 内存泄漏memory leak:对象不会被使用但是gc又无法回收。公摊
    • 单例模式中如果引用了外部对象有可能造成内存泄漏
    • 有些需要close的资源未关闭导致内存泄漏。数据库连接,网络连接
  • stop the word:gc发生时用户线程会被暂停,gc线程执行,完成应用程序的卡顿。
  • 程序中的并行:多个cpu分别各自处理不同的程序进程。即多个事情在同一时间点发生
  • 程序中的并发:一个cpu不断切换不同的程序进程来执行,同一时刻只能执行一个,但看起来像是都在执行。即多个事情在同一时间段发生
  • 垃圾回收的并行与并发
    • 并行:指多条垃圾回收线程同时执行回收工作
    • 串行:指单线程执行回收工作
    • 并发:用户线程和垃圾回收线程同时执行(但并不一定同时,还是会有stw)
  • 安全点
    • 只有在安全点才可以进行垃圾回收
    • 通常将耗时较长的指令作为安全点,例如方法调用,循环跳转,异常跳转
    • 如何确保所有线程在安全点暂停?
      • 抢先式终端:首先中断所有线程,然后检查将未达到安全点的线程执行到安全点
      • 主动式中断:首先设定一个中断标志,然后各线程轮训,如果为真则自行中断挂起
  • 安全区域
    • 指在一段代码片段中对象的引用不会发生变化,这个区域的任何位置gc都是安全的
    • 例如线程的sleep和blocked状态都是安全区域

什么时候发生GC

Minor GC(新生代GC):当jvm无法为新的对象分配空间的时候就会发生Minor gc,所以分配对象的频率越高,也就越容易发生Minor gc

Full GC/Major GC(年老代GC):①当老年代无法分配内存的时候,②当发生Minor GC的时候可能触发Full GC




版权声明:本文为博主原创文章,欢迎转载,转载请注明作者、原文超链接,感谢各位看官!!!

本文出自:monkeyGeek

座右铭:生于忧患,死于安乐

欢迎志同道合的朋友一起交流、探讨!

monkeyGeek
# ,

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×