哦?原来这就是 JVM 垃圾!
大家都知道,JVM 有垃圾回收的机制,垃圾回收的前提是要知道:什么是垃圾!然后再是如何识别垃圾!
什么是垃圾
垃圾,本质上就是没有引用的对象(们),下面来介绍两种垃圾
1. 没有引用指向的对象
下图是对象间引用的状态,从正常引用到引用断开,这个 A 和 C 的引用断开之后,C 就成了那个垃圾。

2. 没有引用指向的一组对象
一个典型的案例如下图,就是循环引用,这几个对象看起来都有引用指向,但是其实他们只是一堆紧紧相拥的垃圾。

如何识别垃圾
上面介绍了什么是垃圾,那要如何才能识别出垃圾呢?主要有两种算法:
- 引用计数法
- 可达性分析法
1. 引用计数法
算法很简单,就是在对象头上加上被引用的次数,对象的被引用的次数为 0 之日,就是其成为垃圾之时!这个算法的优点是垃圾回收及时,只要对象被引用次数为 0,就可以回收了。
下图是引用计数的示意图,对象 A、B、C 都被引用了一次

如果 A 跟 C 的引用断开,则 C 的引用次数减一,变为 0,此时 C 就是垃圾

引用计数法有个致命的缺点:那就是无法识别出循环引用!
下图是一个循环引用,明明他们就是一堆垃圾,但是因为被引用次数都不为 0,引用计数法无法识别出他们是垃圾。

2. 可达性分析法
引用计数法的缺点过于致命,目前 JVM 采用的是另一种算法来识别垃圾:可达性分析法。
这个算法的基本思路就是:从一系列根对象(GC Roots)开始,根据引用关系向下搜索,如果某个对象到 GC Roots 间没有任何引用,则证明此对象是不可能再被使用的,也就是垃圾。
其示意图如下,左边绿色部分的对象,都可以连向 GC Roots,所以他们都是存活的对象。而右边灰色的部分,即使他们是循环引用,他们也跟 GC Roots 之间没有连接路径,所以灰色部分的对象是垃圾。

那么,究竟是哪些对象能成为至高无上的 GC Roots 呢?以下是主要的 GC Roots:
- 虚拟机栈中引用的对象,如各个线程调用的方法堆栈中的参数、局部变量等。
- 方法区中类的静态属性引用的对象,如类的引用类型的静态变量。
- 方法区中常量引用的对象,如字符串常量池里的引用。
- 本地方法栈中 JNI(Native 方法)引用的对象。
- 虚拟机内部的引用,如基本数据类型对应的 Class 对象,一些常驻的异常对象(比如
NullPointExcepiton、OutOfMemoryError)等,还有系统类加载器。
优点:解决引用计数器所不能解决的循环引用问题。
缺点:
- 耗时:因为需要从
GC Roots开始逐个检查引用; - STW:GC 过程中需要保证对象的引用关系不能发生变化,所以 GC 进行时必须停顿所有执行线程(STW:Stop The World)。
总结
第一部分我们介绍了什么是垃圾:没有任何引用指向的一个或多个对象。
第二部分介绍了如何识别垃圾,有两种算法:
- 引用计数法:通过给对象添加被引用的次数来识别。优点是回收简单及时;缺点是无法解决循环引用。
- 可达性分析法:从一系列根对象(
GC Roots)开始,根据引用关系向下搜索,如果某个对象到GC Roots间没有任何引用,则此对象就是垃圾。优点是解决了循环引用;缺点是耗时和 STW。
哦?原来这就是 JVM 垃圾!的更多相关文章
- JDK分析工具&JVM垃圾回收(转)
转自:http://blog.163.com/itjin45@126/blog/static/10510751320144201519454/ 官方手册:http://docs.oracle.com/ ...
- JVM基础系列第8讲:JVM 垃圾回收机制
在第 6 讲中我们说到 Java 虚拟机的内存结构,提到了这部分的规范其实是由<Java 虚拟机规范>指定的,每个 Java 虚拟机可能都有不同的实现.其实涉及到 Java 虚拟机的内存, ...
- JVM垃圾回收机制与内存回收
暂时转于:https://blog.csdn.net/qq_27035123/article/details/72857739 垃圾回收机制 GC是垃圾回收机制,java中将内存管理交给垃圾回收机制, ...
- 图解JVM垃圾内存回收算法
图解JVM垃圾内存回收算法 这篇文章主要介绍了图解JVM垃圾内存回收算法,由于年轻代堆空间的垃圾回收会很频繁,因此其垃圾回收算法会更加重视回收效率,下面博主和大家来一起学习一下吧 前言 首先,我们要讲 ...
- 深入JVM垃圾回收机制,值得你收藏
JVM可以说是为了Java开发人员屏蔽了很多复杂性,让Java开发的变的更加简单,让开发人员更加关注业务而不必关心底层技术细节,这些复杂性包括内存管理,垃圾回收,跨平台等,今天我们主要看看JVM的垃圾 ...
- .Net平台GC VS JVM垃圾回收
前言 不知道你平时是否关注程序内存使用情况,我是关注的比较少,正好借着优化本地一个程序的空对比了一下.Net平台垃圾回收和jvm垃圾回收,顺便用dotMemory看了程序运行后的内存快照,生成内存快照 ...
- JVM垃圾回收机制总结:调优方法
转载: JVM垃圾回收机制总结:调优方法 JVM 优化经验总结 JVM 垃圾回收器工作原理及使用实例介绍
- JVM 垃圾回收器工作原理及使用实例介绍
IBM介绍文档:https://www.ibm.com/developerworks/cn/java/j-lo-JVMGarbageCollection/ Java 的新生代串行垃圾回收器中使用了复制 ...
- JVM 垃圾回收器工作原理及使用实例介绍(转载自IBM),直接复制粘贴,需要原文戳链接
原文 https://www.ibm.com/developerworks/cn/java/j-lo-JVMGarbageCollection/ 再插一个关于线程和进程上下文,待判断 http://b ...
随机推荐
- Pdb— Python的调试器
参考:Pdb- Python的调试器 pdb 模块定义了一个交互式源代码调试器,用于 Python 程序.它支持在源码行间设置(有条件的)断点和单步执行,检视堆栈帧,列出源码列表,以及在任何堆栈帧的上 ...
- Java异常02——自定义异常
Error与Exception与自定义异常 Error与Exception Error Exception 自定义异常 快捷键: ctrl + alt + t package exception.d ...
- 腾讯技术团队整理,为什么 Flutter 能最好地改变移动开发
导语 | Flutter 框架是当下非常热门的跨端解决方案,能够帮助开发者通过一套代码库高效构建多平台精美应用,支持移动.Web.桌面等多端开发.但仍然有很多产品.设计.甚至开发同学并不了解 Flut ...
- .NetCore+Envoy+Id4+Dapr+EFCore 构建微服务之Envoy
.NetCore比较流行的微服务应该时是用Ocelot的方式构建微服务,纯配置化,开发量也比较小.但是做过一些项目之后发现这个方式不是很适合,首先它比较笨重,其次不支持gRpc和webSocket通信 ...
- Build VM Cluster on CentOS Host
Host Machine [root@bocoty49 ~]# lsb_release -a LSB Version: :base-4.0-amd64:base-4.0-noarch:core-4.0 ...
- Git (10)-- 打标签(git tag)
@ 目录 1.列出标签 2.创建标签 2.1.附注标签 2.2.轻量标签 3.后期打标签 4.共享标签 5.删除标签 6.检出标签 超详细 Git 图文版小白教程(持续更新) 像其他版本控制系统(VC ...
- SQL Server 判断数据库中是否存在表
使用场景 可以反复的执行相同脚本 方式1:查询sysobjects表 if EXISTS (SELECT * from sysobjects WHERE name='test_table') DROP ...
- DI 原理解析 并实现一个简易版 DI 容器
本文基于自身理解进行输出,目的在于交流学习,如有不对,还望各位看官指出. DI DI-Dependency Injection,即"依赖注入":对象之间依赖关系由容器在运行期决定, ...
- mongodb中时间跟实际时间相差8小时----时区问题
遇到的问题 参考:mongo中时间跟实际时间相差8小时 Mongo中一个Collection有一个字段用来存放数据的插入时间,但记录的时间比实际时间晚了8小时. 查询得知存储在mongodb中的时间是 ...
- qt 中回调函数的实现
在QT中回调函数主要可以实现多态性,通过回调函数可以动态处理一些操作.在多线程中,当同时需要处理多个事务的时候,显然你会去创建多个线程类然后实例化,这显然会增加开发工作,当我们在线程类中加入一个回调函 ...