JVM垃圾回收(上)
Java 中的垃圾回收,常常是由 JVM 帮我们做好的。虽然这节省了大家很多的学习的成本,提高了项目的执行效率,但是当项目变得越来越复杂,用户量越来越大时,还是需要我们懂得垃圾回收机制,这样也能进行更深一步的优化。
辨别对象存亡
垃圾回收( Garbage Collection,以下简称 GC ),从字面上理解,就是将已经分配出去的,但却不再使用的内存回收回来,以便能够再次分配。
在 JVM 中,垃圾就是指的死亡对象所占据的堆空间( GC 是发生在堆空间中),那么我们如果辨别一个对象是否死亡呢?JVM 使用的是引用计数法
和可达性分析
。
引用计数法
引用计数法( Reference Counting),是为每个对象添加一个引用计数器,用来统计引用该对象的个数。一旦某个对象的引用计数器为0,则说明该对象已经死亡,便可以被回收了。
其具体实现为:
如果有一个引用,被赋值为某一对象,那么将该对象的引用计数器 +1。
如果一个指向某一对象的引用,被赋值为其他值,那么将该对象的引用计数器 -1。
也就是说,我们需要截获所有的引用更新操作,并且相应地增减目标对象的引用计数器。
看似很简单的实现,其实里面有不少缺陷:
- 需要额外的空间来存储计数器。
- 计数器的更新操作十分繁琐。
- 最重要的:无法处理循环引用对象。
针对第3点,举个例子特别说明一下:
假设对象 a 与 b 相互引用,除此之外没有其他引用指向他们。在这种情况下,a 和 b 实际上已经死了。
但由于它们的引用计数器皆不为0(因为相互引用,两者均为1),在引用计数法的计算中,这两个对象还活着。因此,这些循环引用对象所占据的空间将不可回收,从而造成了内存泄露
。
可达性分析
可达性分析( Reachability Analysis ),是目前 JVM 主要采取的判定对象死亡的方法。实质在于将一系列GC Roots
作为初始的存活对象合集(live set),然后从该合集出发,探索所有能够被该集合引用到的对象,并将其加入到该集合中,这个过程我们也称之为标记(mark)。最终,未被探索到的对象便是死亡的,是可以回收的。
那么什么是GC Roots
呢?我们可以暂时理解为由堆外指向堆内的引用,一般而言,GC Roots 包括(但不限于)如下几种:
- Java 方法栈桢中的局部变量
- 已加载类的静态变量
- JNI handles
- 已启动且未停止的 Java 线程
之前我们说引用计数法
会有循环引用的问题,可达性分析
就不会了。举例来说,即便对象 a 和 b 相互引用,只要从 GC Roots 出发无法到达 a 或者 b,那么可达性分析便会认为它们已经死亡。
那可达性分析
有没有什么缺点呢?有的,在多线程环境下,其他线程可能会更新已经分析过的对象中的引用,从而造成误报(将引用设置为 null)或者漏报(将引用设置为未被访问过的对象)。
误报并没有什么伤害,JVM 至多损失了部分垃圾回收的机会。漏报则比较麻烦,因为垃圾回收器可能回收事实上仍被引用的对象内存。一旦从原引用访问已经被回收了的对象,则很有可能会直接导致 JVM 崩溃。
STW
既然可达性分析
在多线程下有缺点,那 JVM 是如何解决的呢?答案便是 Stop-the-world(以下简称JWT
),停止了其他非垃圾回收线程的工作直到完成垃圾回收。这也就造成了垃圾回收所谓的暂停时间(GC pause)。
那 SWT 是如何实现的呢?当 JVM 收到 SWT 请求后,它会等待所有的线程都到达安全点(Safe Point),才允许请求 SWT 的线程进行独占的工作。
那什么又叫安全点呢?安全点是 JVM 能找到一个稳定的执行状态,在这个执行状态下,JVM 的堆栈不会发生变化。
这么一来,垃圾回收器便能够“安全”地执行可达性分析,所有存活的对象也都可以成功被标记,那么之后就可以将死亡的对象进行垃圾回收了。
总结
以上便是发现死亡对象的过程,这也为之后的垃圾回收进行铺垫,具体的垃圾回收过程,我会在下一篇文章中讲述,敬请期待。
有兴趣的话可以访问我的博客或者关注我的公众号、头条号,说不定会有意外的惊喜。
JVM垃圾回收(上)的更多相关文章
- JVM内存管理和JVM垃圾回收机制
JVM内存管理和JVM垃圾回收机制(1) 这里向大家描述一下JVM学习笔记之JVM内存管理和JVM垃圾回收的概念,JVM内存结构由堆.栈.本地方法栈.方法区等部分组成,另外JVM分别对新生代和旧生代采 ...
- JDK分析工具&JVM垃圾回收(转)
转自:http://blog.163.com/itjin45@126/blog/static/10510751320144201519454/ 官方手册:http://docs.oracle.com/ ...
- 老李分享:jvm垃圾回收
老李分享:jvm垃圾回收 poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性能测试,测试工具开发等工作为目标.如果对课程感兴趣,请大家咨询qq:908821478 ...
- jvm - 垃圾回收
jvm - 垃圾回收 注意 : 本系列文章为学习系列,部分内容会取自相关书籍或者网络资源,在文章中间和末尾处会有标注 垃圾回收的意义 它使得java程序员不再时时刻刻的关注内存管理方面的工作. 垃圾回 ...
- JVM垃圾回收机制概述
JVM垃圾回收机制概述 1.定义 是指JVM用于释放那些不再使用的对象所占用的内存. 2.方式 2.1引用计数(早期) 当引用程序创建引用以及引用超出范围时,JVM必须适当增减引用数.当某个对象的引用 ...
- JVM基础系列第8讲:JVM 垃圾回收机制
在第 6 讲中我们说到 Java 虚拟机的内存结构,提到了这部分的规范其实是由<Java 虚拟机规范>指定的,每个 Java 虚拟机可能都有不同的实现.其实涉及到 Java 虚拟机的内存, ...
- Java虚拟机垃圾回收:内存分配与回收策略 方法区垃圾回收 以及 JVM垃圾回收的调优方法
在<Java对象在Java虚拟机中的创建过程>了解到对象创建的内存分配,在<Java内存区域 JVM运行时数据区>中了解到各数据区有些什么特点.以及相关参数的调整,在<J ...
- JVM垃圾回收算法解析
JVM垃圾回收算法解析 标记-清除算法 该算法为最基础的算法.它分为标记和清除两个阶段,首先标记出需要回收的对象,在标记结束后,统一回收.该算法存在两个问题:一是效率问题,标记和清除过程效率都不太高, ...
- JVM垃圾回收算法(最全)
JVM垃圾回收算法(最全) 下面是JVM虚拟机运行时的内存模型: 1.方法区 Perm(永久代.非堆) 2.虚拟机栈 3.本地方法栈 (Native方法) 4.堆 5.程序计数器 1 首先的问题是:j ...
- JVM内存管理、JVM垃圾回收机制、新生代、老年代以及永久代
内存模型 JVM运行时数据区由程序计数器.堆.虚拟机栈.本地方法栈.方法区部分组成,结构图如下所示. JVM内存结构由程序计数器.堆.栈.本地方法栈.方法区等部分组成,结构图如下所示: 1)程序计数器 ...
随机推荐
- JAVA集合框架包含的内容
Java集合框架提供了一套性能优良.使用方便的接口和类,他们位于java.util包中. Collection接口 主要有List.Set等实现类,Map接口主要有HashMap.TreeMap等实现 ...
- Mysql - 高可用方案之MHA
一.概述 本文将介绍mysql的MHA(Master High Availability)方案,官方文档地址:https://github.com/yoshinorim/mha4mysql-manag ...
- composer 依赖的require安装与remove删除命令
安装:require composer require phpmailer/phpmailer 删除:remove composer remove phpmailer/phpmailer
- 疑难杂症----windows7
这两天换了台win7的机器,每次开机发现时间日期没法更新,第一次手动更新后过了一天以后又恢复成20xx/01/01,头疼ing,网上找了好多办法,在这里记录一下,避免以后再碰到同样的问题. 出现这个问 ...
- 2019 DevOps 必备面试题——配置管理篇
原文地址:https://medium.com/edureka/devops-interview-questions-e91a4e6ecbf3 原文作者:Saurabh Kulshrestha 翻译君 ...
- Java优化策略小积累
1.尽量避免大量使用静态变量 package com.cfang.jvm; public class Test2 { private static Test1 test1 = new Test1(); ...
- SpringBoot官方文档学习(一)开发你的第一个Spring Boot应用
一些准备工作: 本节介绍如何开发一个简单的“ Hello World!” Web应用程序,该应用程序重点介绍Spring Boot的一些关键功能.我们使用Maven来构建该项目,因为大多数IDE都支持 ...
- gym102201E_Eat Economically
题意 给\(2n\)个物品,分别有\(a,b\)属性,对于\(i=1...n\),选择\(i\)个\(a\)属性和\(i\)个\(b\)属性,且每个物品只能作为一种属性的贡献,求最小的值. 分析 看了 ...
- SpringBootSecurity学习(06)网页版登录方法级别的权限
用户授权 前面讨论过,Web应用的安全管理,主要包括两个方面的内容,一个是用户身份的认证,即用户登录的设计,二是用户授权,即一个用户在一个应用系统中能够执行哪些操作的权限管理.前面介绍了登录,下面简单 ...
- Player的跟踪狂 -- Camera
P.S.很多游戏里的Player都会设置的被跟踪,是人性的扭曲,还是XXX,正在解密. 第三人称视角 camera紧跟player背后(角度随player改变) using System.Collec ...