JVM垃圾回收(GC)

1. 判断对象是否可以被回收

  • 引用计数法:每个对象有一个引用计数属性,新增一个引用时计数加1,引用释放时计数减1,计数为0时可以回收。此方法简单,但无法解决对象相互循环引用的问题

    // 循环引用
    Node a=new Node();
    Node b=new Node();
    a.next=b;
    b.next=a;
  • 可达性分析:从GC Roots开始向下搜索,搜索所走过的路径称为引用链。当一个对象到GC Roots没有任何引用链时,则证明此对象时不可用的,可以被回收。

为了避免对象相互循环引用的问题,JVM中使用可达性分析判断对象是否可以被回收。

2. 四种引用

2.1 强引用(StrongReference)

大部分引用都是强引用,是使用最普遍的引用。强引用不会被垃圾回收器回收,始终是可达状态。当内存空间不足时,JVM宁可抛出OOM异常,使程序异常终止,也不会通过回收具有强引用的对象来解决内存不足的问题。这是造成Java内存泄漏的重要原因之一。(联系ThreadLocal例子)

2.2 软引用(SoftReference)

对于具有软引用的对象,当内存空间足够时,垃圾回收器不会回收它,若内存空间不够了,就会回收这些对象的内存。软引用可以用来实现内存敏感的高速缓存。

2.3 弱引用(WeakReference)

只要垃圾回收机制运行并发现了具有弱引用的对象,不管当前内存空间是否足够,都会回收该对象的内存。垃圾回收线程的优先级很低,不一定很快发现只具有弱引用的对象。

2.4 虚引用(PhantomReference)

主要作用是用于跟踪对象被垃圾回收的活动。不能单独使用,必须与引用队列(ReferenceQueue)联合使用。当垃圾回收器准备回收一个对象时,如果发现它具有虚引用,就会在回收对象的内存前把这个虚引用加入到与之关联的引用队列中。程序可以通过判断引用队列中是否已经加入虚引用来了解被引用的对象是否要被垃圾回收。

3. 判断废弃常量和无用的类

废弃常量:运行时常量池主要回收废弃常量。如果当前没有任何对象引用该常量,就说明该常量是废弃常量。

无用的类:需要同时满足3个条件。

  • 该类的所有实例都已经被回收,即堆中不存在该类的任何实例。
  • 加载该类的ClassLoader已经被回收
  • 该类对于的java.lang.Class对象没有在任何地方被引用,无法在任何地方通过反射访问该类的方法。

4. 垃圾收集算法

4.1 标记-清除算法(Mark-Sweep)

原理:首先标记出可以回收的对象,在标记完成后统一回收所有被标记的对象。

特点内存碎片化严重、效率低

4.2 复制算法(Copying)

原理:按内存容量将内存划分为大小相同的两块。每次只使用其中的一块,当这一块内存满了之后,将存活的对象复制到未使用的一块中,然后把使用的那一块一次清理。

特点:不易产生内存随便,但效率大大降低。

4.3 标记-整理算法(Mark-Compact)

原理:首先标记出可以回收的对象,然后将存活对象移动至内存的一端,然后清除掉边界外的对象。

特点:根据老年代特点提出的一种标记算法。

4.4 分代收集算法

当前虚拟机的垃圾收集都采用分代收集算法。

新生代,每次收集都会有大量对象死去,所以采用复制算法,只需复出少了对象的复制成本就可以完成每次垃圾收集。

老年代,对象存活几率比较高,每次垃圾回收是时只有少量对象需要被回收,因此采用标记-整理算法进行垃圾收集。

5. 垃圾收集器

JVM针对新生代和老年代分别提供了不同的垃圾收集器。

5.1 Serial收集器(单线程+复制算法)

Serial收集器是最基本的垃圾收集器。Serial是单线程的收集器,只会使用一条垃圾收集线程去完成垃圾收集工作,同时在进行垃圾收集工作时不许暂停其他所有的工作线程("Stop the World"),直到收集结束。

新生代采用复制算法,老年代采用标记-整理算法。

Serial收集器简单高效,对于限定单个CPU环境来说没有线程交互的开销,可以获得最高的单线程垃圾收集效率,因此Serial垃圾收集器时JVM运行在Client模式下默认的新生代垃圾收集器。

5.2 ParNew收集器(Serial+多线程)

ParNew收集器是Serial收集器的多线程版本(多线程并发),除了使用多线程进行垃圾收集外,其余行为和Serial收集器完全一样。

新生代采用复制算法,老年代采用标记-整理算法。

ParNew收集器是运行在Server模式下的JVM的首要选择,除了Serial收集器,只有它能与CMS收集器配合工作。

5.3 Parallel Scavenge收集器

与ParNew收集器类似,但Parallel Scavenge收集器的关注点是吞吐量(高效率地利用CPU)。CMS等垃圾收集器地关注点是用户线程的停顿时间(提高用户体验)。所谓吞吐量就是CPU中用于运行用户代码的时间与CPU总消耗时间的比值。

Parallel Scavenge提供了两个参数用于精确控制吞吐量,分别是控制最大垃圾收集停顿时间的-XX: MaxGCPauseMillis参数以及直接设置吞吐量大小的-XX: GCTimeRatio参数。

5.4 Serial Old收集器(单线程+标记-整理算法)

Serial收集器的老年代版本。它具有两大用途:一种是在JDK1.5及以前的版本中与Parallel Scavenge收集器搭配使用,另一种是作为CMS收集器的后备方案。

5.5 Parallel Old收集器(多线程+标记-整理算法)

Parallel Scavenge收集器的老年代版本,使用多线程和标记-整理算法。在注重吞吐量和CPU资源的场合,可以优先考虑Parallel Scavenge收集器和Parallel Old收集器。

5.6 CMS收集器(多线程+标记-清除算法)

CMS(Concurrent Mark Sweep)收集器是一种以获取最短回收停顿时间为目标的收集器,非常符合在注重用户体验的应用上使用。 CMS收集器是第一款真正意义上的并发收集器,第一次实现了让垃圾回收线程与用户线程(基本上)同时工作。CMS收集器是基于标记-清除算法的。其运行过程包括四个步骤:

  • 初始标记暂停所有其他线程,并记录下直接与GC Roots相连的对象,速度很快;
  • 并发标记:同时开启GC和用户线程,用一个闭包结构去记录可达对象。但在这个阶段结束,这个闭包结构并不能保证包含当前所有的可达对象。因为用户线程可能会不断地更新引用域,所以GC线程无法保证可达性分析的实时性,因此这个算法里会跟踪记录这些发生引用更新的地方。该阶段无需暂停工作线程
  • 重新标记:重新标记阶段就是为了修正并发标记期间因为用户程序继续运行而导致标记产生变动的那一部分对象的标记记录,这个阶段的停顿时间一般会比初始标记阶段的时间稍长,远远比并发标记近阶段的时间短。该阶段仍需要暂停所有工作线程,;
  • 并发清除:开启用户线程,同时GC线程开始清除GC Roots不可达对象,无需暂停工作线程

优点:并发收集、低停顿

缺点:对CPU资源敏感;无法处理浮动垃圾;使用的"标记-清除"会导致收集结束时产生大量内存碎片。

5.7 G1收集器

G1(Garbage First)是面向服务器的垃圾收集器,主要针对配备多核处理器及大容量内存的机器,以极高概率满足GC停顿时间要求的同时还具备高吞吐量性能特征

特点:

  • 并行与并发
  • 分代收集:可以独立管理整个GC堆,但也保留了分代的概念;
  • 空间整合:基于标记-整理算法,不产生内存碎片;
  • 可预测的停顿:相比于CMS,G1可以能建立可预测的停顿时间模型,在不牺牲吞吐量的前提下实现低停顿的垃圾回收。

G1收集器运行步骤大致分为:初始标记;并发标记;最终标记;筛选回收

G1收集器避免全区域垃圾收集,把堆内存划分为大小固定的几个独立区域,并且跟踪这些区域的垃圾收集进度,同时在后台维护一个优先级列表,每次根据所允许的收集时间,优先回收垃圾最多的区域。区域划分和优先级区域回收机制,确保G1收集器可以在有限时间获得最高的垃圾收集效率。

JVM垃圾回收(GC)的更多相关文章

  1. 性能测试三十五:jvm垃圾回收-GC

    垃圾回收-GC 三个问题 哪些内存需要回收? 什么时候回收? 如何回收? YoungGC和FullGC: 新生代引发的GC叫YoungGC 老年代引发的GC叫FullGC FullGC会引起整个Jvm ...

  2. JVM 垃圾回收GC Roots Tracing

    1.跟搜索算法: JVM中对内存进行回收时,需要判断对象是否仍在使用中,可以通过GC Roots Tracing辨别. 定义: 通过一系列名为”GCRoots”的对象作为起始点,从这个节点向下搜索,搜 ...

  3. JVM垃圾回收(GC)流程

    /* 首先介绍一下JVM中堆内存的组成: JVM堆内存主要由三部分组成: (1)新生代: 伊甸园区,存活区,伸缩区 (2)老年代: 老年区,伸缩区 (3)元空间(永久代): 元空间,伸缩区 注意:JD ...

  4. JVM垃圾回收——GC

    一.JVM内存分配与回收 下图为堆内存结构图(注意:元数据区(MetaData )实际上不属于堆): 1.对象优先在Eden区分配 大多数情况下,对象在新生代中Eden区分配.当Eden区没有足够空间 ...

  5. JVM垃圾回收GC

    1.堆的分代和区域 (年轻代)Young Generation(eden.s0.s1  space)    Minor GC (老年代)Old Generation (Tenured space)   ...

  6. JVM—垃圾回收GC算法

    1 GC算法简介 算法 特点 标记-清除 分为"标记"和"清除"两个阶段 复制 可以解决效率问题,将可用的内存按容量划分为大小相等的两块. 标记-整理 先标记. ...

  7. 修改Tomcat的jvm的垃圾回收GC方式为CMS

    修改Tomcat的jvm的垃圾回收GC方式 cp $TOMCAT_HOME/bin/catalina.sh $TOMCAT_HOME/bin/catalina.sh.bak_20170815 vi $ ...

  8. Java:JVM垃圾回收(GC)机制

    JVM垃圾回收算法 1.标记清除(Mark-Sweep) 原理: 从根集合节点进行扫描,标记出所有的存活对象,最后扫描整个内存空间并清除没有标记的对象(即死亡对象)适用场合: 存活对象较多的情况下比较 ...

  9. .Net平台GC VS JVM垃圾回收

    前言 不知道你平时是否关注程序内存使用情况,我是关注的比较少,正好借着优化本地一个程序的空对比了一下.Net平台垃圾回收和jvm垃圾回收,顺便用dotMemory看了程序运行后的内存快照,生成内存快照 ...

随机推荐

  1. 怎样从gitHub上面拉项目

    1.注册 https://gitee.com/oschina 2.拿到代码在gitHub上的地址 3.打开eclipse-->import https://git.oschina.net/cai ...

  2. react中实现可拖动div

    把拖动div功能用react封装成class,在页面直接引入该class即可使用. title为可拖动区域.panel为要实现拖动的容器. 优化了拖动框超出页面范围的情况,也优化了拖动太快时鼠标超出可 ...

  3. 集训 T3-难题

    大致题意: 求方程 \(a_1+a_2+...+a_n=m\) 的非负整数解有几个. 基本思路: 深搜,虽然看起来可能会超时,但是对于100%的数据,0<=n,m<32767,结果< ...

  4. 集训作业 洛谷P1443 马的遍历

    这个题是个搜索,而且有是最少的步数,肯定就是广搜啦,不知道为什么的同学先去学习一下广搜吧. 养成好习惯,看见最少步数就去想想广搜(只是我自己觉得) 竟然这个题可以如此顺畅的想到广搜,感觉不难啊,但还有 ...

  5. 02 安装net-tools工具

    01 登录虚拟机,没错,还是那个熟悉的黑窗口 02 输入用户名密码(我还是习惯使用root用户,因为,它可以为所欲为) 小知识:注意红色框内的符号: 一般用户为限制用户,符号为:$ 超级用户,为无限制 ...

  6. 7.20试机测 T3 阶乘之和 暴力AC题解

    7.20试机测  T3 阶乘之和 暴力AC题解 题外话:此乃本蒟蒻发表的第一篇题解,大家多多关照,支持一下,谢谢 题面 3.阶乘之和(sum.pas/in/out) 问题描述: 给定一个非负整数 n, ...

  7. animate动画基础

    定义: animate() 方法执行 CSS 属性集的自定义动画. 1.该方法通过CSS样式将元素从一个状态改变为另一个状态.CSS属性值是逐渐改变的,这样就可以创建动画效果. 2.只有数字值可创建动 ...

  8. OceanBase安装和使用

    链接 https://mp.weixin.qq.com/s?spm=a2c6h.12873639.0.0.41f92c9bH5FL2Y&__biz=MzU3OTc2MDQxNg==&m ...

  9. android studio 部分问题及解决方案

    1 启动多个虚拟机后开启指定端口的虚拟机     https://blog.csdn.net/chuyouyinghe/article/details/72958004       adb devic ...

  10. SpringBoot学习之整合Druid的简单应用

    一.Druid介绍 Druid简介 Druid是目前Java语言中最好的数据库连接池之一.结合了 C3P0.DBCP 等 DB 池的优点,同时加入了日志监控.Druid 是一个分布式的.支持实时多维 ...