垃圾收集器

判断对象是否需存活

  • 回收堆

    • 判断对象是否存活:

      • 方法一:引用计数法。对象被引用一次就+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. 使用对称加密来加密Spring Cloud Config配置文件

    补充 使用Spring Cloud Config加密功能需要下载JCE扩展,用于生成无限长度的密文.链接:http://www.oracle.com/technetwork/java/javase/d ...

  2. 企业项目实战 .Net Core + Vue/Angular 分库分表日志系统 | 控制反转搭配简单业务

    教程预览 01 | 前言 02 | 简单的分库分表设计 03 | 控制反转搭配简单业务 说明 我们上一节已经成功通过 连接提供程序存储库,获取到了 连接提供程序,但是连接提供程序和数据库连接依赖太深, ...

  3. C++ Templates (1.4 默认模板实参 Default Template Arguments)

    返回完整目录 目录 1.4 默认模板实参 Default Template Arguments 1.4 默认模板实参 Default Template Arguments 可以为模板参数定义默认值,这 ...

  4. 【干货!!】三句话搞懂 Redis 缓存穿透、击穿、雪崩

    前言 如何有效的理解并且区分 Reids 穿透.击穿和雪崩之间的区别,一直以来都挺困扰我的.特别是穿透和击穿,过一段时间就稀里糊涂的分不清了. 为了有效的帮助笔者自己,以及拥有同样烦恼的朋友们区分这三 ...

  5. Windows Server 2012 R2 时间同步

    最近的项目两台服务器都是Windows Server 2012的系统,需要做时间同步,现在是一些从网上搜罗的步骤总结. 具体就是配置windows的注册表: 一.服务端配置 (NTP服务器,客户端将根 ...

  6. Ubuntu 16.04 安装CP210x,CH340驱动

    CH340 https://github.com/juliagoda/CH341SER CP210x 因为源码版本不是linux-source-4.15.0-91-generic,导致error,一个 ...

  7. Vue根据条件添加 click 事件

    方式一:在绑定事件中直接添加标示量clickFlag <div @click="clickFlag && addGoodsHandler()"> XXX ...

  8. 【MarkDown】github readme添加图片 Markdown语法添加图片,适用各种markdown语法

    作者:程序员小冰,CSDN博客:http://blog.csdn.net/qq_21376985, QQ986945193 微博:http://weibo.com/mcxiaobing 首先给大家看一 ...

  9. EditText设置输入的类型,只能输入纯数字,只能输入手机号码,只能输入邮箱等等。

    作者:程序员小冰,CSDN博客:http://blog.csdn.net/qq_21376985转载请说明出处. 下面以数字.电话为例讲述EditText怎么设置输入类型,其他类型可以参考InputT ...

  10. P4609 建筑师

    题目描述 小 Z 是一个很有名的建筑师,有一天他接到了一个很奇怪的任务:在数轴上建 n 个建筑,每个建筑的高度是 1 到 n 之间的一个整数. 小 Z 有很严重的强迫症,他不喜欢有两个建筑的高度相同. ...