垃圾收集器

判断对象是否需存活

  • 回收堆

    • 判断对象是否存活:

      • 方法一:引用计数法。对象被引用一次就+1,当为0时回收对象。缺点:无法解决循环引用问题。
      • 方法二:可达性分析算法。记录当前对象是否有和GC Roots中对象的引用链。(其中,可以作为GCRoots对象的有:虚拟机栈中引用的对象、方法去中类静态属性引用的对象、方法区中常量引用的对象、本地方法栈中引用的对象。)
        • 不可达对象并不是一定被垃圾收集的,当这个对象有必要执行finalize()并finalize里自己和某个对象建立关联,即可在第二次标记时被移出“即将回收”的集合。但强烈建议不在finalize()里来拯救对象,使用try-finally等其他方式或许更好。
    • 引用分为:强引用(new出来的)、软引用(SoftReference类实现)、弱引用(WeakReference类实现)、虚引用(PhantomReference类实现)。是为了描述一类对象:内存空间还够的时候能保存在内存,不够就可以抛弃这些对象。
  • 回收方法区
    • 主要是回收方法区中的废弃常量无用的类

      • 废弃常量:假如在常量池中存在字符串 "abc",如果当前没有任何 String 对象引用该字符串常量,就说明常量 "abc" 就是废弃常量
      • 无用的类必须满足三点:Java堆中不存在该类实例;加载该类的ClassLoader已经被回收;该类对应的java.lang.Class对象没有在其他地方被引用。
      • 无用的类不一定要被回收,可以通过参数与进行控制。

垃圾收集算法(内存回收方法论)

  • 分代收集算法:把堆对象分为新生代(存活率低的对象)和老年代(存活率高的对象)。

    • 老年代:

      • 方法一:标记-清除算法:把要回收的对象标记一下,然后清除。缺点:标记和清除两个操作效率低、会造成空间碎片可能导致二次回收。
      • 方法二:标记- 整理算法:把要回收的对象标记一下,然后留下的对象连续排。
    • 新生代:复制算法
      • 把堆内存分为两部分,只使用其中的一部分装对象,当装不进去后,把留存对象拷贝到另一部分,连续放置。
      • 两部分比例可以超过1:1比如9:1,但要使用内存担保,用老年代的内存空间担保,即1放不下时候放老年代去。所以只适合新生代使用。

HotSpot的算法实现(HotSpot如何发起内存回收)

  • 关于枚举根节点:

    • HotSpot中,使用OopMap数据结构使虚拟机直接指导哪些地方存着对象引用,这样GC扫描时可以直接得知这些信息。
    • 具体地,类加载完成后,HotSpot就把对象内什么偏移量是什么数据类型算出来。JIT编译过程中,也会记录下栈和寄存器中哪些位置是引用。
  • 安全点:
    • 因为对象引用是变化的,所以OopMap是变化的,但不可能每一时刻都记录对应的OopMap,故只有在安全点才记录了OopMap,GC只有在安全点才回发生,使线程暂停。
    • 如何让所有线程跑到安全点才停下来?主流采用主动式中断,在安全点设置标志,各个线程主动去轮询到没到标志,到了的话就停下。
  • 安全区域:
    • 当程序不执行的时候,即没有分配CPU时间的时候,无法响应JVM的中断请求走到安全点挂起,这就需要安全区域。
    • 安全区域是指在一段代码片段中,引用关系不发生变化。
    • 当线程执行到安全区域,就标识进入安全区域,此时JVM发起GC就不用管这个线程了,当线程要离开安全区域时,检查是否已完成了GC,完成即可离开安全区域。

垃圾收集器(内存回收的具体实现、特点)

重点1:CMS(Concurrent Mark Sweep)收集器:老年代收集器

  • 并发的收集器
  • 以减少用户线程的停顿,加快响应速度为目标
  • 基于标记-清除算法
  • 步骤
    • 1 初始标记:标记和GC Roots直接关联的对象(stop worlds)。
    • 2 并发标记:垃圾回收线程和用户线程并发,进行可达性分析,标记所有和GC Roots相连的节点。
    • 3 重新标记:由于上一步可能会有标记更改,对这些更改进行重新标记(stop worlds)。
    • 4 标记清除:垃圾回收线程和用户线程并发,进行标记请清除
  • 缺点
    • 1 对CPU资源敏感。因为占用了一部分线程,所以虽然减少停顿,但会导致应用程序变慢,尤其是CPU资源少的时候。
    • 2 无法处理浮动垃圾。由于4标记清除是并发进行的,这一过程用户线程新产生的垃圾本次无法处理,并且要预留一部分内存空间给此时产生的垃圾,如果预留的不够,就会造成本次垃圾收集失败,导致再次GC。
    • 3 由于使用标记-清除算法,所以会产生内存碎片。

重点2:G1 (Garbage-First) 收集器:自己可以负责全部的GC收集

  • G1是一款面向服务器的垃圾收集器,主要针对配备多颗处理器及大容量内存的机器,以极高概率满足 GC 停顿时间要求的同时,还具备高吞吐量性能特征。
  • 特点
    • 可以不与其他垃圾收集器配合独自管理GC,但是在内部仍保留分代概念。
    • 整体基于标记-整理算法,局部基于复制算法。
    • 可预测的停顿时间:建立可预测的停顿时间模型,能让使用者明确指定stop worlds在一个长度为 M 毫秒的时间片段内。 内部实现:使用 Region 划分内存空间,G1 收集器在后台维护了一个优先列表,每次根据允许的收集时间,优先选择回收价值最大的 Region。保证了 GF 收集器在有限时间内可以尽可能高的收集效率(把内存化整为零)。
    • 并行与并发:可利用多颗cpu、多核优势,减少stop worlds 时间。并且支持并发。
  • 步骤
    • 初始标记
    • 并发标记
    • 最终标记
    • 筛选回收

Serial收集器(新生代、单线程、复制算法、Client模式)、ParNew收集器(新生代、多线程、复制算法、Server模式)、Serial Old收集器(老年代、单线程、标记整理算法、Client模式)、CMS

这其中的新生代可以与老年代搭配使用。

Parallel Scavenge收集器(新生代、多线程、重吞吐、有自适应调节策略、复制算法) 、Parallel Old收集器(老年代、多线程、标记整理算法)

两者可搭配使用。

重吞吐是指应用程序总体完成时间短,但停顿可能大一些,适合后台、用户交互少的应用。

理解GC日志

GC日志包含:发生时间、停顿类型(GC/Full GC)、DefNew等表示GC发生的区域时新生代/老年代/永久代、GC前后内存总容量变化、堆内存容量变化。

Minor GC 与 Major GC

  • 新生代 GC(Minor GC):指发生新生代的的垃圾收集动作,Minor GC 非常频繁,回收速度一般也比较快。
  • 老年代 GC(Major GC/Full GC):指发生在老年代的 GC,出现了 Major GC 经常会伴随至少一次的 Minor GC(并非绝对),Major GC 的速度一般会比 Minor GC 的慢 10 倍以上。

内存分配

todo

参考连接

https://github.com/Snailclimb/JavaGuide/blob/master/docs/java/jvm/JVM垃圾回收.md#46-cms-收集器

[深入理解JVM虚拟机]第3章-垃圾收集器、内存分配策略的更多相关文章

  1. 《深入理解java虚拟机》读书笔记——垃圾收集与内存分配策略

    可回收判定两种算法 引用计数法(Reference Counting):引用为0时可回收. 可达性分析法(Reachability Analysis): 从GCRoots对象到这个对象不可达. GCR ...

  2. 深入理解Java虚拟机 第三章 垃圾收集器 笔记

    1.1   垃圾收集器 垃圾收集器是内存回收的具体实现.以下讨论的收集器是基于JDK1.7Update14之后的HotSpot虚拟机.这个虚拟机包含的所有收集器有: 上图展示了7种作用于不同分代的收集 ...

  3. [Note][深入理解Java虚拟机] 第三章 垃圾收集器与内存分配策略笔记

    书上关于GCTimeRatio的讲解有点难以理解,查看Oracle的文档后重新理解了下 -XX:GCTimeRatio 运行时间 / GC时间 当GCTimeRatio为19时,运行时间是GC时间的1 ...

  4. 深入理解java虚拟机(2)------垃圾收集器和内存分配策略

    GC可谓是java相较于C++语言,最大的不同点之一. 1.GC回收什么? 上一篇讲了内存的分布. 其中程序计数器栈,虚拟机栈,本地方法栈 3个区域随着线程而生,随着线程而死.这些栈的内存,可以理解为 ...

  5. 深入理解JVM(5)——垃圾收集和内存分配策略

    1.垃圾收集对象 垃圾收集主要是针对堆和方法区进行. 程序计数器.虚拟机栈和本地方法栈这三个区域属于线程私有的,只存在于线程的生命周期内,线程结束之后也会消失,因此不需要对这三个区域进行垃圾回收. 哪 ...

  6. 深入理解JVM(5)——HotSpot垃圾收集器详解

    HotSpot虚拟机提供了多种垃圾收集器,每种收集器都有各自的特点,没有最好的垃圾收集器,只有最适合的垃圾收集器.根据新生代和老年代各自的特点,我们应该分别为它们选择不同的收集器,以提升垃圾回收效率. ...

  7. JVM基础学习(二):内存分配策略与垃圾收集技术

    Java与C++之间有一堵由内存动态分配和垃圾收集技术所围成的高墙,墙外面的人想进去,墙里面的人却想出来 垃圾收集概述 Java内存模型中的堆和方法区是垃圾收集技术所需要关注的终点,因为其他的区域会跟 ...

  8. [深入理解JVM虚拟机]第2章-Java内存区域与内存溢出异常

    2.0引-Java内存区域中,栈内存和堆内存分别装什么,为什么? 栈:解决程序的运行问题,即程序如何执行,或者说如何处理数据. 堆:解决的是数据存储的问题,即数据怎么放,放在哪儿. 参考链接https ...

  9. <<深入Java虚拟机>>-第三章-垃圾收集器与内存分配策略-学习笔记

    垃圾收集 垃圾收集(Garbage Collection,GC),垃圾收集需要完成的三件事情. 哪些对象需要回收 什么时候回收 如何回收 如何确定对象已死(即不可能在被任何途径引用的对象) 引用计数算 ...

随机推荐

  1. LeetCode 91,点赞和反对五五开,这题是好是坏由你来评判

    本文始发于个人公众号:TechFlow,原创不易,求个关注 今天是LeetCode专题的第57篇文章,我们一起来看看LeetCode第91题,解码方法(Decode ways). 这道题官方给定的难度 ...

  2. unity探索者之微信支付,非第三方插件

    版权声明:本文为原创文章,转载请声明http://www.cnblogs.com/unityExplorer/p/8404604.html 相比微信的登录和分享功能,微信支付sdk的接入显得相当简单, ...

  3. oracle创建用户操作

    打开命令提示框输入以下内容 1.输入:sqlplus /nolog //进入oralce控制台2.输入:conn /as sysdba //以管理员权限登录3.输入:create user abc i ...

  4. oracle 将数据库的表复制到另一个数据库表内

    将数据库A中的表sys_role复制到数据库B中在数据库b中的SQL工作表写如下代码: 第一步:建立链接 CREATE database link A //数据库名称CONNECT to text  ...

  5. springMVC入门(五)------统一异常处理

    简介 系统中异常包括两类:预期异常和运行时异常RuntimeException,前者通过异常捕获获取异常信息,后者需通过规范代码.提高代码路绑定减少运行时异常的发生 异常处理思路:无论dao层.ser ...

  6. 用find命令删除某目录下及所有子目录中某类型的特定文件

    当前目录下含有多级子目录,并且每一个子目录下都含有多个文件,如何删除当前目录及所有子目录下特定类型的文件,比如:*.pyc(所有文件名以“*.pyc”结尾的文件): 可以使用find命令,将当前目录下 ...

  7. 牛客网PAT-练兵场-挖掘机技术哪家强

    题目地址:https://www.nowcoder.com/pat/6/problem/4058 题解:用数组下标当学校编号.输入一次数据的时候,直接在相应数组下标位置累加内容,同时更新最大的总分的学 ...

  8. CentOS 7环境下大量创建账号的方法

    1 一些账号相关的检查工具 1.1 pwck命令 pwck 这个指令在检查 /etc/passwd 这个账号配置文件内的信息,与实际的家目录是否存在等信息,还可以比对 /etc/passwd /etc ...

  9. day38:MySQL数据库之约束&索引&外键&存储引擎

    目录 part1:数据类型 part2:约束 part3:主键索引 PRI &唯一索引 UNI &普通索引 MUL part4:外键:foreign key part5:在外键中设置联 ...

  10. 全局api 2020/8/14

    // 注意:每次调用 $.get() 或 $.post() 或 $.ajax() 的时候, // 会先调用 ajaxPrefilter 这个函数 // 在这个函数中,可以拿到我们给Ajax提供的配置对 ...