JVM学习笔记(四)

文章目录

  • JVM学习笔记(四)
    • 笔记链接
    • 1.GC算法
      • 1.1GC-判断对象是否可回收
        • 1.1.1 引用计数法
        • 1.1.1 可达性分析
      • 1.2GC-回收算法
        • 标记清除法(Mark-Sweep)
        • 标记整理法(Mark-Compact)
        • 复制算法(copy)
        • 1.2.1 分代收集算法(重点)
          • 1. 新生代和复制算法
          • 2. 老年代与标记整理算法
        • 分区收集算法
    • 2.GC垃圾收集器
      • 2.1 垃圾收集器的种类
      • 2.2 Serial垃圾收集器
      • 2.3 ParNew垃圾收集器
      • 2.4 Parallel Scavenge 收集器
      • 2.5 Serial Old收集器
      • 2.6 Parallel Old收集器
      • 2.7 CMS 收集器
      • 2.8 G1收集器

笔记链接

JVM学习笔记(一)
JVM学习笔记(二)
JVM学习笔记(三)
JVM学习笔记(四)

(待更新…)

1.GC算法

1.1GC-判断对象是否可回收

1.1.1 引用计数法

​ 在 Java 中,引用和对象是有关联的。显然引用计数法,即一个对象如果没有任何与之关联的引用,即他们的引用计数为 0,则说明对象不太可能再被用到,那么这个对象就是可回收对象。

方案: 给对象维护一个引用计数器,当有一个地方引用到它,则计数器加1,当有引用失效,则计数器减1,当为0时,说明没有地方引用到这个对象。

  • 优点: 实现简单、效率高
  • 缺点: 无法解决循环引用。(致命缺点)

循环引用问题: 假设栈中有两引用A,B,对应堆中的对象分别为a,b,而对象a,b中有相互指向的引用C和D,现在A=null,B=null,栈中已经没有引用指向对象a和b,但对象中C和D引用相互指向,所以a,b无法释放。

如图效果:

1.1.1 可达性分析

为了解决引用计数法的循环引用问题,Java 使用了可达性分析的方法。

通过一系列的“GC roots”对象作为起点搜索。如果在“GC roots”和一个对象之间没有可达路径,则称该对象是不可达的。要注意的是,不可达对象不等价于可回收对象,不可达对象变为可回收对象至少要经过两次标记过程。两次标记后仍然是不可达对象,则将面临回收。

图片:

图中的a,b对象将会被回收。

1.2GC-回收算法

标记清除法(Mark-Sweep)

法如其名,分为两个阶段,标注和清除。标记阶段标记出所有需要回收的对象,清除阶段回收被标记的对象所占用的空间。

  • 缺点: 内存碎片化。

如图:

标记整理法(Mark-Compact)

标记阶段和 Mark-Sweep 算法相同,标记后不是清理对象,而是将存活对象移向内存的一端。然后清除端边界外的对象。

如图:

复制算法(copy)

按内存容量将内存划分为等大小的两块。每次只使用其中一块,当这一块内存满后将尚存活的对象复制到另一块上去,把已使用的内存清掉。回顾:GC中minor GC用的算法。

  • 优点: 内存效率高,不易产生碎片

  • 缺点: 浪费一定量的空间(要找地方放复制的对象)

图片:

1.2.1 分代收集算法(重点)

现在绝大部分的JVM在使用的算法,其实就是根据堆的老年代和新生代而划分使用上面三种GC中的某几种。老生代的特点是每次垃圾回收时只有少量对象需要被回收,新生代的特点是每次垃圾回收时都有大量垃圾需要被回收,因此可以根据不同区域选择不同的算法。

1. 新生代和复制算法

新生代通常使用复制算法,From和To区域就是这样来的,以为复制算法需要交换区来保存存活对象。为新生代中每次垃圾回收都要回收大部分对象,即要复制的操作比较少,但通常并不是按照 1:1 来划分新生代。而是按照8:1:1来划分(这个是HotSpot虚拟机的默认比例)。o( ̄▽ ̄)ブ,来回顾一下前面的笔记:

由于频繁创建对象,所以新生代会频繁触发MinorGC 进行垃圾回收。当 Eden 区内存不够的时候就会触发 MinorGC,对新生代区进行一次垃圾回收。MinorGC使用的是复制算法,过程如下:

  1. MinorGC会把Eden Space+From Space扫描一边
  2. 扫描过后将存活的对象复制到 To Space 区域,并对对象的年龄进行+1
  3. 然后清空Eden Space+From Space的对象
  4. 最后,将To Space和From Space标志互换(不移动对象,区域的标志更换,就是To变成From),To Space等待下次MinorGC的回收。
2. 老年代与标记整理算法

老年代因为每次只回收少量对象,因而一般采用 Mark-Compact 算法。老样子回顾一下,这次整合一下:

  1. MinorGC会把Eden Space+From Space扫描一边
  2. 扫描过后将存活的对象复制到 To Space 区域,并对对象的年龄进行+1
  3. 然后清空Eden Space+From Space的对象
  4. 最后,将To Space和From Space标志互换(不移动对象,区域的标志更换,就是To变成From),To Space等待下次MinorGC的回收。
  5. 当老年区满了以后(一般以为MinorGC后存活的对象无法放到老年区),垃圾回收器会对老年区进行清理。
  6. 标记老年区中的存活对象后,将存活对象移向内存的一端。
  7. 然后清除端边界外的对象。

分区收集算法

分区算法则将整个堆空间划分为连续的不同小区间, 每个小区间独立使用, 独立回收.。

2.GC垃圾收集器

​ 堆内存被划分为新生代和年老代两部分,新生代主要使用复制和标记-清除垃圾回收算法;年老代主要使用标记-整理垃圾回收算法,因此 java 虚拟中针对新生代和年老代分别提供了多种不同的垃圾收集器。垃圾回收器是GC的执行者,所以前面的笔记并没有特别说明Full GC和Major GC是指定用那种算法进行回收,其实不同垃圾回收器对不同的区域进行垃圾回收,而且不同垃圾回收器使用的算法并不完全一致。下面我就要介绍垃圾回收器的种类。o( ̄▽ ̄)ブ

2.1 垃圾收集器的种类

垃圾回收器主要分三大类:

  • 新生代收集器:Serial、ParNew、Parallel Scavenge
  • 老年代收集器:CMS、Serial Old、Parallel Old
  • 整堆收集器: G1

HotSpot JVM (JDK1.6)的垃圾回收器情况图

2.2 Serial垃圾收集器

Serial是最基本垃圾收集器,Serial使用的算法和线程类型如下:

  • 算法: 复制算法
  • 线程: 单线程
  • 区域: 新生代

Serial 是一个单线程的收集器,**在进行垃圾收集的同时,必须暂停其他所有的工作线程,直到垃圾收集结束。(多CPU下也如此)**Serial 垃圾收集器虽然在收集垃圾过程中需要暂停所有其他的工作线程,但是它简单高效,对于限定单个 CPU 环境来说,没有线程切换的开销。单核单CPU的情况下可以获得最高的单线程垃圾收集效率。

Serial和Serial Old执行过程如下图:

2.3 ParNew垃圾收集器

​ ParNew 垃圾收集器其实是 Serial 收集器的多线程版本,也使用复制算法,除了使用多线程进行垃圾收集之外,其余的行为和 Serial 收集器完全一样。

  • 算法: 复制算法
  • 线程: 多线程
  • 区域: 新生代

ParNew 收集器默认开启和 CPU 数目相同的线程数,可以通过下面JVM参数调节

-XX:ParallelGCThreads

ParNew垃圾收集器是很多 java虚拟机运行在 Server 模式下新生代的默认垃圾收集器。

2.4 Parallel Scavenge 收集器

Parallel Scavenge 收集器也是一个新生代垃圾收集器,在垃圾收集过程中也是需要暂停所有的工作线程有以下特点:

  • 算法: 复制算法
  • 线程: 多线程
  • 调节策略: 自适应调节策略(根据吞吐量控制)
  • 区域: 新生代

Parallel Scavenge是一种非常高效的垃圾收集器,它使用吞吐量来控制垃圾回收的时间,吞吐量公式如下:

吞吐量=运行用户代码shi间运行用户代码时间+垃圾收集时间吞吐量=\frac{运行用户代码shi间}{运行用户代码时间+垃圾收集时间} 吞吐量=运行用户代码时间+垃圾收集时间运行用户代码shi间​

高吞吐量可以最高效率地利用 CPU 时间,尽快地完成程序的运算任务,主要适用于在后台运算而不需要太多交互的任务。Parallel Scavenge追求的是高吞吐量。自适应调节策略也是 ParallelScavenge 收集器与 ParNew 收集器的一个重要区别

2.5 Serial Old收集器

Serial Old 是 Serial 垃圾收集器年老代版本,老年代一般使用标志整理算法(Mark-compact),跟Serial 垃圾收集器一样,是单线程,也一样要停掉其他线程的运行。运行在 Serial Old是Client 默认的 java 虚拟机默认的老年代垃圾收集器,跟Serial不同,Serial是Client 默认的 java 虚拟机默认的新生代垃圾收集器。

  • 算法: 标志整理算法
  • 线程: 单线程
  • 区域: 老年代

Serial和Serial Old执行过程如下图:

2.6 Parallel Old收集器

从名字上就知道,Parallel Old 收集器是Parallel Scavenge的年老代版本,行为上跟Parallel Scavenge基本一样,而算法不同。Parallel Old 正是为了在年老代同样提供吞吐量优先的垃圾收集器。

  • 算法: 标志整理算法
  • 线程: 多线程
  • 区域: 老年代
  • 提供时间: JDK1.6

Parallel Scavenge 和Parallel Old 搭配运行过程图:

2.7 CMS 收集器

Concurrent mark sweep(CMS)收集器是老年代垃圾收集器,主要目标是获取最短垃圾回收停顿时间,使用的算法跟其他老年代的垃圾收集器有所不同,使用的是标记清除算法。一般用在一些交互比较高的程序,最短时间的停顿,能有效确保交互程序和用户交互的体验。

  • 算法: 标志清除算法
  • 线程: 多线程
  • 区域: 老年代

CMS工作机制:

  1. 初始标记:只是标记一下 GC Roots 能直接关联的对象,速度很快,但暂停所有的工作线程。
  2. 并发标记:进行 GC Roots 跟踪的过程,和用户线程一起工作。
  3. 重新标记:为了修正在并发标记期间,因用户程序继续运行而导致标记产生变动的那一部分对象的标记记录,仍然需要暂停所有的工作线程。
  4. 并发清除:清除 GC Roots 不可达对象,和用户线程一起工作,不需要暂停工作线程。

各阶段的耗时:

  • 初始标记:耗时短(简易标志,速度快)
  • 并发标记:耗时较长(跟踪)
  • 重新标记:耗时短(补全并发标记时,程序变化的那部分,标记量小)
  • 并发清除:耗时较长(清除)

结论:总体上来看CMS 收集器的内存回收和用户线程是一起并发地执行。

工作过程图:

2.8 G1收集器

Garbage First(G1)是垃圾收集领域的最新成果,同时也是HotSpot在JVM上力推的垃圾收集器,并赋予取代CMS的使命。

找到两篇很好的博客
https://blog.csdn.net/renfufei/article/details/41897113.

https://blog.csdn.net/coderlius/article/details/79272773.

  1. G1的设计原则是"首先收集尽可能多的垃圾(Garbage First)"。因此,G1并不会等内存耗尽(串行、并行)或者快耗尽(CMS)的时候开始垃圾收集,而是在内部采用了启发式算法,在老年代找出具有高收集收益的分区进行收集。同时G1可以根据用户设置的暂停时间目标自动调整年轻代和总堆大小,暂停目标越短年轻代空间越小、总空间就越大;
  2. G1采用内存分区(Region)的思路,将内存划分为一个个相等大小的内存分区,回收时则以分区为单位进行回收,存活的对象复制到另一个空闲分区中。由于都是以相等大小的分区为单位进行操作,因此G1天然就是一种压缩方案(局部压缩);
  3. G1虽然也是分代收集器,但整个内存分区不存在物理上的年轻代与老年代的区别,也不需要完全独立的survivor(to space)堆做复制准备。G1只有逻辑上的分代概念,或者说每个分区都可能随G1的运行在不同代之间前后切换;
  4. G1的收集都是STW的,但年轻代和老年代的收集界限比较模糊,采用了混合(mixed)收集的方式。即每次收集既可能只收集年轻代分区(年轻代收集),也可能在收集年轻代的同时,包含部分老年代分区(混合收集),这样即使堆内存很大时,也可以限制收集范围,从而降低停顿。
    . G1虽然也是分代收集器,但整个内存分区不存在物理上的年轻代与老年代的区别,也不需要完全独立的survivor(to space)堆做复制准备。G1只有逻辑上的分代概念,或者说每个分区都可能随G1的运行在不同代之间前后切换;
  5. G1的收集都是STW的,但年轻代和老年代的收集界限比较模糊,采用了混合(mixed)收集的方式。即每次收集既可能只收集年轻代分区(年轻代收集),也可能在收集年轻代的同时,包含部分老年代分区(混合收集),这样即使堆内存很大时,也可以限制收集范围,从而降低停顿。

JVM学习笔记(四)相关推荐

  1. JVM学习笔记(四)------内存调优

    首先需要注意的是在对JVM内存调优的时候不能只看操作系统级别Java进程所占用的内存,这个数值不能准确的反应堆内存的真实占用情况,因为GC过后这个值是不会变化的,因此内存调优的时候要更多地使用JDK提 ...

  2. jvm学习笔记(三)

    jvm学习笔记(三) 文章目录 jvm学习笔记(三) 1.全部笔记链接 2.堆 2.1堆的划分 使用JVM参数查看划分 Hotspot堆内存划分图(JDK8之前) 2.2 GC对堆的回收 GC的种类 ...

  3. jvm学习笔记(二)

    jvm学习笔记(二) 文章目录 jvm学习笔记(二) 1.全部笔记链接 2. Native关键字 3.关于JVM规范 3.1 JVM规范中运行时数据区的概念 4.HotSpot的JVM运行时数据区 4 ...

  4. jvm学习笔记(一)

    jvm学习笔记(一) 文章目录 jvm学习笔记(一) 1.全部笔记链接 3.类加载器 作用 类别 加载步骤 获得类加载器 4.双亲委派机制 5.沙箱安全机制 沙箱概念 JAVA沙箱的基本组件 基本组件 ...

  5. 【JVM学习笔记】内存回收与内存回收算法 就哪些地方需要回收、什么时候回收、如何回收三个问题进行分析和说明

    目录 一.相关名词解释 垃圾收集常用名词 二.哪些地方需要回收 本地方法栈.虚拟机栈.程序计数器 方法区 Java堆 三.什么时候回收 1. 内存能否被回收 内存中的引用类型 引用计数算法 可达性分析 ...

  6. JVM学习笔记(Ⅰ):Class类文件结构解析(带你读懂Java字节码,这一篇就够了)

    JVM学习笔记(Ⅰ):Class类文件结构解析,带你读懂Java字节码 前言:本文属于博主个人的学习笔记,博主也是小白.如果有不对的地方希望各位帮忙指出.本文主要还是我的学习总结,因为网上的一些知识分 ...

  7. JVM学习笔记汇总:结合尚硅谷宋红康老师视频教程及PPT

    JVM学习笔记汇总:结合尚硅谷宋红康老师视频教程及PPT 第一章:JVM虚拟机的介绍 1.1虚拟机的分类 虚拟机通常分为两类:系统虚拟机和程序虚机.其中,系统虚拟机是指完全对物理计算机的仿真,而程序虚 ...

  8. JVM学习笔记之GUI监控工具

    目录 背景 jConsole 本地连接:连接本地计算机一个正在运行的JVM进程 远程连接:连接JMX代理 高级连接:使用特殊的URL连接JMX代理 VisualVM 插件安装 连接方式 本地连接:连接 ...

  9. C#可扩展编程之MEF学习笔记(四):见证奇迹的时刻

    前面三篇讲了MEF的基础和基本到导入导出方法,下面就是见证MEF真正魅力所在的时刻.如果没有看过前面的文章,请到我的博客首页查看. 前面我们都是在一个项目中写了一个类来测试的,但实际开发中,我们往往要 ...

最新文章

  1. USACO 1.2-Transformations
  2. 【BZOJ1226】[SDOI2009] 学校食堂
  3. html提值到php 冒泡,如何实现Html事件冒泡
  4. iOS获取label的高度模仿博友
  5. 【转】Redis学习---阿里云Redis多线程性能增强版详解
  6. python算法入门
  7. 电子密码锁设计(附源码和原理图)
  8. matlab中换行操作
  9. android绘制半圆弧线_android canvas使用line画半圆
  10. Error response from daemon: conflict: unable to delete acdcfe83bcc5 (must be forced) - image is bein
  11. 上海国际能源交易中心大户持仓报告制度 操作指南
  12. mysql命令行安装教程_MySQL命令行教程
  13. mysql类型转换及小数点保留问题(cast函数)
  14. 鸿门宴 项伯为什么要保护刘邦
  15. 【MySQL】表数据的增删查改(DML)
  16. 部署storm和配置文件详解
  17. CV全新范式 | LSTM在CV领域杀出一条血路,完美超越Swin与ConvNeXt等前沿算法
  18. Golang 开发的一站式云原生 PaaS 平台 —— Erda
  19. 淡盐水洗脸有什么用处
  20. 深力科电子SND101系列兼容代替SLM561A 支持PWM调光 线性恒流LED驱动芯片

热门文章

  1. React.js 2016 最佳实践 徬梓阅读 1584收藏 71
  2. IIS_FastCGI+php5.3+wincache+memcached+ZendLoader
  3. hackerrank---Sets - Symmetric Difference
  4. 新书上市:《FLUENT 14.0超级学习手册》
  5. oracle TNS: 协议适配器错误 解决办法
  6. CNN基础知识(1)
  7. C#--WinForm项目主窗体设计
  8. SpringBoot集成EasyPoi实现Excel导入导出
  9. mysql 小数点后几位不足补0初始化
  10. PHP文件函数 记录日志功能