深入理解JVM垃圾回收机制

1、垃圾回收需要解决的问题及解决的办法总览

  • 1、如何判定对象为垃圾对象

    • 引用计数法
    • 可达性分析法
  • 2、如何回收
    • 回收策略

      • 标记-清除算法
      • 复制算法
      • 标记-整理算法
      • 分带收集算法
    • 垃圾回收器
      • serial
      • parnew
      • Cms
      • G1
  • 3、何时回收

下面就是如何判定对象为垃圾对象


2、引用计数法

在对象中添加一个引用计数器,当有地方引用这个对象的时候,引用技术器得值就+1,当引用失效的时候,计数器得值就-1

算法缺点:当某个引用被收集时,下个引用并不会清0,因此不被回收造成内存泄露。

下面我们运行实例代码来看,JVM在循环引用时,是否能被收集(如果回收了就说明垃圾回收器用的不是引用计数法)。

如果想打印日志信息,请填入如下参数。

-verbose:gc -XX:+PrintGCDetails

其中我们需要将每个对象的所占内存扩大,因此我们声明一个大点的空间。

测试实验代码如下:

public class A {
private Object instance;
public A() {
byte[] m = new byte[20*1024*1024];
}
public static void main(String[] args) {
A a1 = new A();
A a2 = new A();
a1.instance=a2;
a2.instance=a1; a1=null;
a2=null;
System.gc();
//parallel 默认采用的垃圾回收器
}
}

运行结果如下所示:

[GC (System.gc()) [PSYoungGen: 22446K->648K(37888K)] 42926K->21136K(123904K), 0.0011193 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]

[Full GC (System.gc()) [PSYoungGen: 648K->0K(37888K)] [ParOldGen: 20488K->519K(86016K)] 21136K->519K(123904K), [Metaspace: 2632K->2632K(1056768K)], 0.0074751 secs] [Times: user=0.02 sys=0.00, real=0.01 secs]

Heap

PSYoungGen total 37888K, used 328K [0x00000000d6000000, 0x00000000d8a00000, 0x0000000100000000)

eden space 32768K, 1% used [0x00000000d6000000,0x00000000d6052030,0x00000000d8000000)

from space 5120K, 0% used [0x00000000d8000000,0x00000000d8000000,0x00000000d8500000)

to space 5120K, 0% used [0x00000000d8500000,0x00000000d8500000,0x00000000d8a00000)

ParOldGen total 86016K, used 519K [0x0000000082000000, 0x0000000087400000, 0x00000000d6000000)

object space 86016K, 0% used [0x0000000082000000,0x0000000082081fd8,0x0000000087400000)

Metaspace used 2638K, capacity 4486K, committed 4864K, reserved 1056768K

class space used 281K, capacity 386K, committed 512K, reserved 1048576K

这里我们会看到 22446K->648J这里,我们的对象被回收了,这就说明我们JVM采用的垃圾回收算法并不是引用计数法。


3、可达性分析法

算法如名,可达性分析法就是从GCroot结点开始,看能否找到对象。

GCroot结点开始向下搜索,路径称为引用链,当对象没有任何一条引用链链接的时候,就认为这个对象是垃圾,并进行回收。

那么什么是GCroot呢(虚拟机在哪查找GCroot)。

  • 虚拟机栈(局部变量表)
  • 方法区的类属性所引用的对象。
  • 方法区中常量所引用的对象。
  • 本地方法栈中引用的对象。

目前主流JVM采用的垃圾判定算法就是可达性分析法。


至此垃圾判定算法结束

垃圾回收算法开始


4、标记-清除算法

存在的问题:

  • 效率问题。
  • 内存小块过多。

    如图所示:黄色的就是被标记清除的。清除后会发现有很多多余的小块。


5、复制算法

下面是java内存常规划分

  • (线程共有)堆内存 方法区
  • (栈内存 本地方法栈) 程序计数器

下面是堆内存的划分

  • 新生代

    • Eden 伊甸园
    • Survivor 存活区
    • Tenured Gen 养老区
  • 老年代

下面就是过程:

被标记的黑色就是需要回收的

将白色区域复制下面,然后清空上面的



这样就完成了内存的连续分配,但是引来一个问题。

每次只能使用一半的内存。是不是有点少。。

为了解决这个问题,我们对内存就进行了划分。

我们对内存分为了三块区域。

内存区域 所占百分比
Eden 80%
survivor 10%
Tenured Gen 一点点

复制算法,我们需要将上面的思路,将Eden中需要回收的对象放到Survivor,然后清除。

也就是俩个Survivor中进行复制与清除。

这里我们即提高了效率,又减少了内存分配。

如果Survivor不够放,那就扔到老年代里,或者其他方法,反正有内存担保。


6、标记-整理算法

复制算法主要针对新生代内存收集方法。

标记-整理算法主要针对的是老年代内存收集方法。

主要步骤:标记-整理-清除

如下图所示

然后将右面的进行删除计科达到回收效果。

7、分代收集算法

分代收集算法是根据内存的分代选择不同的算法。

对于新生代,一般选择复制算法。

对于老年代,一般选择标记-整理-清除算法。

显而易见,这是上面俩种算法的优点糅合在一起的应用。


至此我们总结了所有垃圾回收算法。

下面就是各种出名的垃圾收集器


8、Serial收集器

特点:

  • 出现的最早的,发展最悠久的垃圾收集器。
  • 单线程垃圾收集器。
  • 主要针对新生代内存进行收集

运行机制如下所示

缺点:慢

用处:在客户端上运行还是比较有效。没有线程的开销,所以在客户端还是比较好用的。


9、ParNew收集器

特点:

  • 由单线程变成了多线程垃圾收集器。
  • 如果要用CMS进行收集的话,最好采用ParNew收集器。

实现原理都是复制算法。

缺点:

  • 性能较慢

10、Parallel Scavenge 收集器

主用算法:复制算法(新生代收集器)

吞吐量 = (执行用户代码消耗的时间)/(执行用户代码的时间)+ 垃圾回收时所占用的时间

优点:吞吐量优化(CPU用于运行用户代码的时间与CPU消耗的总时间的比值)

关于控制吞吐量的参数如下

-XX:MaxGCPauseMills #垃圾收集器的停顿时间
-XX:GCTimeRatio #吞吐量大小

当停顿时间过小时,内存对应变小,回收的频率增大。因此第一个参数需要设置的合理才比较好。

第二个参数值越大,吞吐量越大,默认是99,(垃圾回收时间最多只能占到1%)

总的来说:客户端可用,服务端最好不用。


11、CMS收集器(Concurrent Mark Sweep)

采用算法:标记清除算法。

  • 工作过程:

    • 初始标记
    • 并发标记
    • 重新标记
    • 并发清理
  • 优点:
    • 并发收集
    • 低停顿
  • 缺点:
    • 占用大量的CPU资源
    • 无法处理浮动垃圾
    • 出现ConcurrentMode Failure
    • 空间碎片

CMS是一个并发的收集器。

目标是:减少延迟,增加响应速度

执行效果如下所示:

  • 初始标记

    • 可达性分析法
  • 重新标记
    • 为了修正并发期间,因对象重新运作而修正
  • 并发清理
    • 直接清除了

12、G1收集器(面向服务端)

最牛的垃圾收集器。

  • 历史

    -2004年Sun发表了第一篇G1的论文,到2006年左右,在JDK6内集成进去了。JDK7才放出来。
  • 优势
    • 集中了前面所有收集器的优点
    • G1能充分利用了多核的并行特点,能缩短停顿时间。
    • 分代收集(分成各种Region)
    • 空间整合(类似于标记清理算法)
    • 可预测的停顿()。
  • 步骤
    • 初始标记
    • 并发标记
    • 最终标记
    • 筛选回收

13、小结:

至此我们就已经掌握了大部分GC的知识。这可不是一个小工程,希望要好好吸收知识。。

JVM垃圾回收?看这一篇就够了!的更多相关文章

  1. JVM垃圾回收篇

    点赞再看,养成习惯,微信搜索「小大白日志」关注这个搬砖人. 文章不定期同步公众号,还有各种一线大厂面试原题.我的学习系列笔记. 基础概念 GC=jvm垃圾回收,垃圾回收机制是由垃圾回收器Garbage ...

  2. jvm - 垃圾回收

    jvm - 垃圾回收 注意 : 本系列文章为学习系列,部分内容会取自相关书籍或者网络资源,在文章中间和末尾处会有标注 垃圾回收的意义 它使得java程序员不再时时刻刻的关注内存管理方面的工作. 垃圾回 ...

  3. Java虚拟机学习笔记——JVM垃圾回收机制

    Java虚拟机学习笔记——JVM垃圾回收机制 Java垃圾回收基于虚拟机的自动内存管理机制,我们不需要为每一个对象进行释放内存,不容易发生内存泄漏和内存溢出问题. 但是自动内存管理机制不是万能药,我们 ...

  4. JVM内存模型你只要看这一篇就够了

    JVM内存模型你只要看这一篇就够了 我是一只孤傲的鱼鹰 让我们不厌其烦的从内存模型开始说起:作为一般人需要了解到的,JVM的内存区域可以被分为:线程栈,堆,静态方法区(实际上还有更多功能的区域,并且这 ...

  5. JDK分析工具&JVM垃圾回收(转)

    转自:http://blog.163.com/itjin45@126/blog/static/10510751320144201519454/ 官方手册:http://docs.oracle.com/ ...

  6. JVM基础系列第8讲:JVM 垃圾回收机制

    在第 6 讲中我们说到 Java 虚拟机的内存结构,提到了这部分的规范其实是由<Java 虚拟机规范>指定的,每个 Java 虚拟机可能都有不同的实现.其实涉及到 Java 虚拟机的内存, ...

  7. Java虚拟机垃圾回收:内存分配与回收策略 方法区垃圾回收 以及 JVM垃圾回收的调优方法

    在<Java对象在Java虚拟机中的创建过程>了解到对象创建的内存分配,在<Java内存区域 JVM运行时数据区>中了解到各数据区有些什么特点.以及相关参数的调整,在<J ...

  8. JVM内存管理、JVM垃圾回收机制、新生代、老年代以及永久代

    内存模型 JVM运行时数据区由程序计数器.堆.虚拟机栈.本地方法栈.方法区部分组成,结构图如下所示. JVM内存结构由程序计数器.堆.栈.本地方法栈.方法区等部分组成,结构图如下所示: 1)程序计数器 ...

  9. JVM垃圾回收算法及回收器详解

    引言 本文主要讲述JVM中几种常见的垃圾回收算法和相关的垃圾回收器,以及常见的和GC相关的性能调优参数. GC Roots 我们先来了解一下在Java中是如何判断一个对象的生死的,有些语言比如Pyth ...

随机推荐

  1. 给debian的docker容器添加crontab定时任务

    现在大部分的docke镜像是基于debian # cat /etc/issue Debian GNU/Linux 9 \n \l Docker容器是不支持后台服务的,像systemctl servic ...

  2. (十八)c#Winform自定义控件-提示框

    前提 入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章. 开源地址:https://gitee.com/kwwwvagaa/net_winform_custom_control ...

  3. abp(net core)+easyui+efcore实现仓储管理系统——使用 WEBAPI实现CURD (十四)

    abp(net core)+easyui+efcore实现仓储管理系统目录 abp(net core)+easyui+efcore实现仓储管理系统——ABP总体介绍(一) abp(net core)+ ...

  4. 《MyCat分库分表策略详解》

    在我们的项目发展到一定阶段之后,随着数据量的增大,分库分表就变成了一件非常自然的事情.常见的分库分表方式有两种:客户端模式和服务器模式,这两种的典型代表有sharding-jdbc和MyCat.所谓的 ...

  5. d3.js制作蜂巢图表带动画效果

    以上是效果图,本图表使用d3.js v4制作.图表主要功能是在六边形格子中显示数据,点击底部图标可以切换指定格子高亮显示,图表可以随浏览器任意缩放. 1.图表的主体结构是由正六边形组成,使用d3生成六 ...

  6. Leetcode之回溯法专题-47. 全排列 II(Permutations II)

    Leetcode之回溯法专题-47. 全排列 II(Permutations II) 给定一个可包含重复数字的序列,返回所有不重复的全排列. 示例: 输入: [1,1,2] 输出: [ [1,1,2] ...

  7. CSAPP - Ch 1 - 计算机系统漫游

    目录 0 序言及摘要 1 信息就是位+上下文 2 程序被其他程序翻译成不同的格式 3 了解编译系统如何工作是大有益处的 0 序言及摘要 (1) 序言: CS:APP -- Computer Syste ...

  8. Agentless监控实践中的预警指标采集

    很多公司已经开发了监控解决方案,解决了指标收集.展示.预警发送等一系列问题. 本文介绍的监控解决方案由高性能时序数据库InfluxDB.时序分析监控工具Grafana及Agentless自动化工具An ...

  9. HTML(五)列表,区块,布局,表单和输入

    HTML 列表 无序列表 Coffee Tea Milk 默认是圆点,也可以 圆圈 正方形 有序列表 Coffee Tea Milk Coffee Tea Milk 默认是用数字排序 大写字母 小写字 ...

  10. P3317 [SDOI2014]重建 变元矩阵树定理 高斯消元

    传送门:https://www.luogu.org/problemnew/show/P3317 这道题的推导公式还是比较好理解的,但是由于这个矩阵是小数的,要注意高斯消元方法的使用: #include ...