• JVM垃圾回收


    回收的区域:java堆与方法区。

    程序计数器、虚拟机栈、本地方法栈三个区域随线程而生,随线程而灭,不需要考虑内存回收的问题。

    方法区进行垃圾收集的“性价比”一般比较低:在堆中,尤其是在新生代中,常规应用进行一次垃圾收集一般可以回收70%~95%的空间,而永久代的垃圾收集效率远低于此。

    故垃圾回收主要考虑的是堆。

    判断对象存活算法

    引用计数法

    给对象添加引用计数器,每当有地方引用它时,计数器加1;引用失效时减1;计数器为0表示对象不再被使用。

    优点:实现简单、判定效率高。

    缺点:难以解决对象之间相互引用的问题(两个废弃的对象相互引用,计数器都为1)。

    可达性分析算法

    GC Roots为起始点,GC Roots到某个对象的路径为引用链,当一个对象到GC Roots没有任何引用链时,该对象不在被使用(可回收)。

    可作为GC Roots的对象有:

    虚拟机栈中引用的对象。

    本地方法栈中JNI引用的对象。

    方法区中类静态属性引用的对象。

    方法区中常量引用的对象。

    垃圾收集算法

    标记-清理算法

    首先标记所有需要回收的对象,然后统一回收所有被标记的对象。

    不足: 效率问题,标记与清理的效率都不高;

                空间问题,清理后产生大量不连续的内存碎片。

     复制算法

    将内存分为大小相等的两块,每次只使用其中的一块。当一块内存用完了,将其中还存活的对象复制到另一块内存中,然后清理这一块内存。

    缺点:内存缩小为原来的一半。

     一种改进方法是,将内存分为较大的一块Eden空间和较小的两块Survivor空间,每次使用Eden与其中的一块Survivor。回收时,将Eden和Survivor中还存活的对象复制到另一块Survivor空间上,然后清理Eden与用过的Survivor。

    标记-整理算法

    标记需要回收的对象,将所有存活的对象向一端移动,清理边界以外的内存。

     分代收集算法

    将java堆分为新生代与老年代,新生代选用复制算法,老年代选用标记-清理算法或标记-整理算法。

    (新生代与老年代内容见 JVM新生代与老年代

    垃圾回收器

    Serial收集器

    serial(串行)这是一个单线程收集器。也就是说,它在进行垃圾回收时,必须暂停其他所有线程。显然,有时垃圾回收停顿的比较久的话,这对于用户来说是很难受的。

     

    ParNew

    这个收集器和Serial很类似,进行垃圾回收的时候,也是得暂停其他所有线程,不过,它可以多条线程工作进行垃圾回收。

    Parallel Scavenge收集器

    parallel,并行的意思。也是可以多线程进行垃圾回收处理,但是它与ParNew不同。它会严格控制垃圾回收的时间与执行其他代码的时间之间的比例。我们来看一个名词:吞吐量。

    吞吐量 = 运行用户代码时间 / (运行用户代码时间 + 垃圾收集时间)。

    也就是说,Parallet Scavenge收集器会严格控制吞吐量,至于这个吞吐量是多少,这个可以人为设置。

    CMS(Concurrent Mark Sweep)收集器

    CMS收集器是基于“标记-清除”算法实现的,它的运作过程相对于前面几种收集器来说要更复杂一些,整个过程分为4个步骤,包括:

    1. 初始标记(CMS initial mark)
    2. 并发标记(CMS concurrent mark)
    3. 重新标记(CMS remark)
    4. 并发清除(CMS concurrent sweep)

    其中初始标记、重新标记这两个步骤仍然需要暂停其他线程。但另外两个步骤可以和其他线程并发执行。初始标记仅仅只是标记一下GCRoots能直接关联到的对象,速度很快,并发标记阶段就是进行GC Roots Tracing的过程 (说白了就是把整个图都遍历了,找出没有的对象),

    而重新标记阶段则是为了修正并发标记期间,因用户程序继续运作而导致标记产生变动的那一部分对象的标记记录,这个阶段的停顿时间一般会比初始标记阶段稍长一些,但远比并发标记的时间短。

    由于整个过程中耗时最长的并发标记和并发清除过程中,收集器线程都可以与用户线程一起工作,所以总体上来说,CMS收集器的内存回收过程几乎是与与用户线程一起并发地执行。

     

    G1收集器

    该收集器具有如下特点:

    1. 并行与并发:G1能充分利用现代计算器多CPU,多核的硬件优势,可以使用并发或并行的方式来缩短让其他线程暂停的优势。
    2. 分代收集:就是类似像分出新生代和老年代那样处理。
    3. 空间整合:采用了复制算法+标记-整合算法的特点来回收垃圾。就是整体采用标记-整理算法,局部采用复制算法。
    4. 可预测停顿:这个就牛了,就是说,它能让使用者明确指定在一个长度为M毫秒的时间片段内,消耗在垃圾收集上的时间不超过N毫秒。

    它的执行过程大体如下:

    1. 初始标记。
    2. 并发标记。
    3. 最终标记。
    4. 筛选回收。

    这个流程和CMS很相似,它也是在初始标记和最终标记需要暂停其他线程,但其他两个过程就可以和其他线程并发执行。

    刚才我们说了G1收集器哪些优点,例如可预测停顿,这也使得筛选回收,是可以预测停顿垃圾回收的时间的,也就是说,停顿的时间是用户自己可以控制的,这也使得一般情况下,在筛选回收的时候,我们会暂停其他线程的执行,把所有时间都用到筛选回收上。

    另有推荐阅读:

    JVM垃圾回收器详解

    JVM垃圾回收机制

  • 相关阅读:
    良许 | 同事的一个动作,让我熬夜的工作全部白费……
    良许 | 命令的输出不会保存?居然连 tee 命令都不会用!
    良许 | 从命令行同时移动多个文件类型的小技巧
    良许Linux | Linux学习方法及学习资料汇总
    JAVA基础篇 之 方法的重载
    Spring学习笔记(八)Spring Data JPA学习
    java基础篇 之 位运算符
    Spring Cloud Stream学习(五)入门
    SpringCloudStream学习(四)TTL(存活时间)Dead Letter Exchanges(死信交换机)
    SpringCloudStream学习(三)RabbitMQ中的惰性队列
  • 原文地址:https://www.cnblogs.com/deltadeblog/p/9491877.html
Copyright © 2020-2023  润新知