JVM—垃圾收集器
JVM—垃圾收集器
什么是垃圾
没有被引用的对象就是垃圾。
怎么找到垃圾
引用计数法
当对象引用消失,对象就称为垃圾。
对象消失一个引用,计数减去一,当引用都消失了,计数就会变为0.此时这个对象就会变成垃圾。

在堆内存中主要的引用关系有如下三种:单一引用、循环引用、无引用:

引用计数法性能比较低。
引用计数算法不能解决循环引用问题,为了解决这个问题,JVM使用了根可达分析算法。
根可达算法
根可达算法的基本思路就是通过一系列的名为GCRoot的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链(Reference Chain),当一个对象到GCRoot没有任何引用链相连时,则证明此对象是不可用的,也就是不可达的。
可作GCRoots的对象:
- 虚拟机栈中,栈帧的本地变量表引用的对象。
- 方法区中,类静态属性引用的对象。
- 方法区中,常量引用的对象。
- 本地方法栈中,JNI引用的对象。
回收过程
即使在可达性分析算法中不可达的对象,也并非是"非死不可"。被判定不可达的对象处于"缓刑"阶段。要真正宣告死亡,至少要经历两次标记过程:
- 第一次标记:如果对象可达性分析后,发现没有与GC Roots相连接的引用链,那它将会被第一次标记;
- 第二次标记:第一次标记后,接着会进行一次筛选。筛选条件:此对象是否有必要执行finalize()方法。在finalize()方法中没有重新与引用链建立关联关系的,将被进行第二次标记。
第二次标记成功的对象将真的会被回收,如果失败则继续存活。
对象引用
在JDK1.2之后,Java对引用的概念进行了扩充,将引用分为强引用(StrongReference)、软引用(SoftReference)、弱引用(WeakReference)、虚引用(PhantomReference)四种,这四种引用强度依次逐渐减弱。
| 引用类型 | 被垃圾回收的时间 | 用途 | 生存时间 |
|---|---|---|---|
| 强引用 | 从来不会 | 对象的一般状态 | JVM停止时终止 |
| 软引用 | 内存不足时 | 对象缓存 | 内存不足时终止 |
| 弱引用 | 正常GC | 对象缓存 | GC后终止 |
| 虚引用 | 正常GC | 类似事件回调机制 | GC后终止 |
| 无引用 | 正常GC | 对象的一般状态 | GC后终止 |
强引用
代码中普遍存在,只要强引用还在,就不会被GC。
Object obj = new Object();
软引用
非必须引用,内存溢出之前进行回收,如内存还不够,才会抛异常。
Object obj = new Object();
SoftReference<Object> sf = new SoftReference<Object>(obj);
obj = null;
Object o = sf.get();//有时会返回null
System.out.println("o = " + o);
应用场景:软引用可用来实现内存敏感的高速缓存。
举例如下:
- 应用需要读取大量本地文件,如果每次读取都从硬盘读取会严重影响性能,如果一次性全部加载到内存,内存可能会溢出。
- 可以使用软引用解决这个问题,使用一个HashMap来保存文件路径和文件对象管理的软引用之间的映射关系。
- 内存不足时,JVM会自动回收缓存文件对象的占用空间,有效地避免了OOM问题。
弱引用
非必须引用,只要有GC,就会被回收。
Object obj = new Object();
WeakReference<Object> wf = new WeakReference<Object>(obj);
obj = null;
//System.gc();
Object o = wf.get();//有时候会返回null
boolean enqueued = wf.isEnqueued();//返回是否被垃圾回收器标记为即将回收的垃圾
System.out.println("o = " + o);
System.out.println("enqueued = " + enqueued);
- 弱引用是在第二次垃圾回收时回收,短时间内通过弱引用取对应的数据,可以取到,当执行过第二次垃圾回收时,将返回null。
- 作用:监控对象是否已经被垃圾回收器标记为即将回收的垃圾,可以通过弱引用的isEnQueued方法返回对象是否被垃圾回收器标记。
虚引用
- 虚引用是最弱的一种引用关系。垃圾回收时直接回收
- 一个对象是否有虚引用的存在,完全不会对其生存时间构成影响,也无法通过虚引用来取得一个对象实例。
Object obj = new Object();
PhantomReference<Object> pf = new PhantomReference<Object>(obj, new
ReferenceQueue<>());
obj=null;
Object o = pf.get();//永远返回null
boolean enqueued = pf.isEnqueued();//返回是否从内存中已经删除
System.out.println("o = " + o);
System.out.println("enqueued = " + enqueued);
- 虚引用是每次垃圾回收的时候都会被回收,通过虚引用的get方法永远获取到的数据为null,因此也被成为幽灵引用。
- 作用:跟踪戏象被垃圾回收的状态,仅仅是提供一种确保对象被回收后,做某些事情的机制。类似事件监听机制
如何清除垃圾
JVM提供3种方法,清除垃圾对象:
- Mark-Sweep标记清除算法
- Copyirvg拷贝算法
- Mark-Compact标记压缩算法
标记清除算法(Mark-Sweep)
最基本的算法,主要分为标记和清除两个阶段。首先标记出所有需要回收的对象,在标记完成后统一回收掉所有被标记的对象。
缺点:
- 效率不高,标记和清除过程的效率都不高;
- 空间碎片,会产生大量不连续的内存碎片,会导致大对象可能无法分配,提前触发GC。
拷贝算法(Copying)
为解决效率。它将可用内存按容量划分为相等的两块,每次只使用其中的一块。当这一块的内存用完了,就将还存活着的对象复制到另外一块上面,然后再把已使用过的内存空间一次清理掉。
一般采用这种收集算法来回收新生代,当回收时,将Eden和Survivor中还存活着的对象拷贝到另外一块Survivor空间上,最后清理掉Eden和刚才用过的Survivor的空间。
HotSpot虚拟机默认Eden和Survivor的大小比例是8:1,也就是每次新生代中可用内存空间为整个新生代容量的90%(80%+10%),只有10%的内存是会被“浪费”的。当Survivor空间不够用时,需要依赖其他内存(这里指老年代)进行分配担保(Handle Promotion)。
- 优点:没有碎片化,所有的有用的空间都连接在一起,所有的空闲空间都连接在一起;
- 缺点:存在空间浪费;
标记-整理算法(Mark-Compact)
老年代没有人担保,不能用复制回收算法。可以用标记-整理算法,标记过程仍然与“标记-清除”算法一样,然后让所有存活的对象都向一端移动,然后直接清理掉端边界以外的内存。
缺点:性能较低,因为除了拷贝对象以外,还需要对象内存空间进行压缩,所以性能较低。
分代回收(Generational Collection)
当前商业虚拟机都是采用这种算法。根据对象的存活周期的不同将内存划分为几块。
- 新生代,每次垃圾回收都有大量对象失去,选择复制算法。
- 老年代,对象存活率高,无人进行分配担保,就必须采用标记清除或者标记整理算法。
用什么清除垃圾
有 8 种不同的垃圾回收器,它们分别用于不同分代的垃圾回收。
- 新生代回收器:Serial、ParNew、Parallel Scavenge
- 老年代回收器:Serial Old、Parallel Old、CMS
- 整堆回收器:G1、ZGC
JVM—垃圾收集器的更多相关文章
- JVM调优:HotSpot JVM垃圾收集器
HotSpot JVM垃圾收集器 - Snooper - 博客园https://www.cnblogs.com/snooper/p/8718478.html
- JVM垃圾收集器-Parallel Scavenge收集器
今天我给大家讲讲JVM垃圾收集器-Parallel Scavenge收集器 Parallel Scavenge收集器 Parallel Scavenge收集器也是一个新生代收集器,它也是使用复制算法的 ...
- 7种JVM垃圾收集器特点,优劣势、及使用场景
今天继续JVM的垃圾回收器详解,如果说垃圾收集算法是JVM内存回收的方法论,那么垃圾收集器就是内存回收的具体实现. 一.常见的垃圾收集器有3类 1.新生代的收集器包括 Serial PraNew Pa ...
- 【006】【JVM——垃圾收集器总结】
Java虚拟机学习总结文件夹 JVM--垃圾收集器总结 垃圾收集器概览 收集算法是内存回收的方法论.垃圾收集据是内存回收的详细实现.Java虚拟机规范中对垃圾收集器应该怎样实现没有规定.不同的厂 ...
- 第五章 JVM垃圾收集器(1)
说明:垃圾回收算法是理论,垃圾收集器是回收算法的实现,关于回收算法,见<第四章 JVM垃圾回收算法> 1.七种垃圾收集器 Serial(串行GC)-- 复制 ParNew(并行GC)-- ...
- 第六章 JVM垃圾收集器(2)
上一章记录了几种常见的垃圾收集器,见<第五章 JVM垃圾收集器(1)> 1.G1 说明: 从上图来看,G1与CMS相比,仅在最后的"筛选回收"部分不同(CMS是并发清除 ...
- JVM垃圾收集器(1)
此文已由作者赵计刚薪授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 说明:垃圾回收算法是理论,垃圾收集器是回收算法的实现,关于回收算法,见<第四章 JVM垃圾回收算法& ...
- 5种JVM垃圾收集器特点和8种JVM内存溢出原因
先来看看5种JVM垃圾收集器特点 一.常见垃圾收集器 现在常见的垃圾收集器有如下几种: 新生代收集器: Serial ParNew Parallel Scavenge 老年代收集器: Serial O ...
- 7种 JVM 垃圾收集器特点、优劣势及使用场景(多图)
7种 JVM 垃圾收集器特点.优劣势及使用场景(多图) mp.weixin.qq.com 点击上方"IT牧场",选择"设为星标"技术干货每日送达! 一.常见垃 ...
- JVM垃圾收集器
JVM中垃圾的回收由垃圾收集器进行,随着JDK的不断升级,垃圾收集器也开发出了各种版本,垃圾收集器不断优化的动力,就是为了实现更短的停顿. 下面是7种不同的分代收集器,如果两个收集器之间有连线,则表示 ...
随机推荐
- 【Azure Cloud Service(Extended Support)】如何使用外延服务迁移应用?
问题一:迁移到云服务扩展后,之前经典版的云服务的部署槽会变成单一的部署槽,关于两个云服务扩展版之间的部署交换能否提供一个演示? 对于具有双槽的云服务(Classic),根据文档中的建议,在迁移到云服务 ...
- 【Azure 环境】使用 az ad group create 时候遇见 Insufficient privileges to complete the operation
问题描述 使用China Azure,通过Azure CLI 创建AAD组报错,提示权限不足 Insufficient privileges to complete the operation # 使 ...
- ExoPlayer播放流程解析
ExoPlayer的播放解析流程如下(以音频为例): 注意: 1.LoadControl.shouldContinueLoading控制是否继续加载. 2.调用setPlayWhenReady(tru ...
- Codeforces Round 920 (Div. 3)(A~F)
目录 A B C D E F A 按题意模拟即可 #include <bits/stdc++.h> #define int long long #define rep(i,a,b) for ...
- redis开启多端口
Centos安装多端口的redis服务 背景 redis默认端口6379,由于开发需要,key有重复.于是另起端口6380. 配置服务过程 1.新建/etc/redis6380.conf,内容如下: ...
- crc16校验C语言源码实例解析
一 概念: 循环冗余码校验英文名称为Cyclical Redundancy Check,简称CRC.它是利用除法及余数的原理来作错误侦测(Error Detecting)的.实际应用时,发送装置计算出 ...
- ubuntu 14.04 x86_64编译安装Skyeye1.3.5RC1的心得
PS:要转载请注明出处,本人版权所有. PS: 这个只是基于<我自己>的理解, 如果和你的原则及想法相冲突,请谅解,勿喷. 前置说明 本文发布于 2014-11-09 09:19:03 ...
- 说JS作用域,就不得不说说自执行函数
一个兜兜转转,从"北深"回到三线城市的小码农,热爱生活,热爱技术,在这里和大家分享一个技术人员的点点滴滴.欢迎大家关注我的微信公众号:果冻想 前言 不得不吐槽,学个JS,这个概念也 ...
- 记录--Threejs-着色器实现一个水波纹
这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 hree.js 是一个基于 WebGL 的 JavaScript 3D 库,用于创建和渲染 3D 图形场景. 一. 图像渲染过程 1.we ...
- drools中使用全局变量
一.背景 在我们编写drools的规则文件的时候,有些时候需要用到全局变量,那么这个该怎么实现呢?有哪些注意事项呢? 二.前置知识 1.语法结构 2.全局变量的特点 使用global来定义全局变量,它 ...