这货到底还是不是垃圾?【垃圾回收GC算法JVM篇四】
垃圾收集 Garbage Collection 通常被称为“GC”, 在jvm 中,程序计数器、虚拟机栈、本地方法栈都是随线程而生随线程而灭,栈帧随着方法的进入和退出做入栈和出栈操作,实现了自动的内存清理,因此,我们的内存垃圾回收主要集中于 java 堆和方法区中,在程序运行期间,这部分内存的分配和使用都是动态的!
@
既然是垃圾回收,那肯定要知道什么是垃圾了是吧,我相信哪一天落魄java开发宜春小哥哥去捡垃圾维持生活,哈气、一juo、弯腰、开盖、倒水,一气呵成我闭着眼,把广东靓仔没喝完的快乐肥宅水错当垃圾捡了,这广东靓仔还不得打人?是的,而JVM的垃圾收集的前提就是明确啥是垃圾!JVM首先会进行一系列计数算法判断是不是垃圾。在JVM认为是否是垃圾的评判标准为对象是否存活,对象存活就不是垃圾,不能进行回收,反之进行回收。
1、判断对象是否存活的JVM两种计数算法
判断对象是否存活的JVM两种计数算法主要有两种,分别是:引用计数、可达性分析计数算法。
一听到计数算法中有“ 算法 ”二字,小白童鞋发愣了:妈呀,数学不好,完了,不学了...咳咳咳,咋们不提算法,从咋们的日常生活开始着手,在我们平时一个东西经常没被使用,而且也用不上什么地方,那么这个东西可以说就是垃圾。其实在 Java 中也是如此,如果一个对象不可能再被引用,那么这个对象就是垃圾,应该被回收。就是这么简单粗暴,JVM两种计数算法就是这样子的,真的不复杂。
1.1、引用计数算法
根据我们生活上的思想,我们很容易想到使用引用计数的方法来判断垃圾。在一个对象被引用时加一,被去除引用时减一,这样我们就可以通过判断引用计数是否为0来判断一个对象是否为垃圾。这种方法我们一般称之为「引用计数法」。确实贼简单的一个思路也正是以为它的简单,从而存在缺陷,因此引用计数算法是这样定义的
1、引用计数:每个对象有一个引用计数属性,新增一个引用时计数加1,引用释放时计数减1,计数为0时可以回收。
2、正因方法简单,从而引用计数算法无法解决对象相互循环引用的问题。
小白童鞋可能不知道啥是对象循环引用,熊dei看图
1.2、可达性分析计数算法
首先声明一点:在实际开发语言比如java、C#等都是采用可达性分析计数算法判断对象是否存活!
可达性分析算法的定义如下:
可达性分析(Reachability Analysis):从
GC Roots
开始向下搜索,搜索所走过的路径称为引用链。当一个对象到GC Roots没有任何引用链相连时,则证明此对象是不可用的。不可达对象。
相信很容易看出,其实都很好理解,唯独GC Roots有点抽象,那啥是GC Roots呢?在Java语言中,GC Roots主要包括:
1、对象的引用,位于虚拟机栈中。
2、方法区中的静态引用。
3、本地方法栈中JNI的引用。【JNI一般指的是Native方法】
简单地说,GC Root 就是经过精心挑选的一些引用
像上面的循环引用的这种情况引用计数算法是无法进行GC掉的,而根搜索算法可以做到,因此引用计数算法存在缺陷!根搜索算法更好!
2、垃圾收集算法
以上内容概述了啥垃圾,接下来就要讲讲如何进行回收垃圾!在生活中我们收集垃圾,可以一边走一边扫,也可以把垃圾全都扫到一起再一次清理。在JVM中,类似生活,提供了一系列的垃圾收集算法。
而且我们还经常能看到垃圾分类,分成可回收垃圾,和不可回收垃圾,但是从某一意义上来讲,还都是垃圾,如果人人都遵守垃圾分类规则,我估计以后收破烂的大叔大妈都天天从可回收垃圾桶下手了,其实在JVM中也类似如此,JVM采取了分区、分代收集的思想。
常见的垃圾回算法:标记清除算法、复制算法、标记整理算法、分代收集算法。
2.1、标记清除算法复制算法
标记清除算法。从名字可以看到其分为两个阶段:标记阶段和清除阶段。一种可行的实现方式是,在标记阶段,标记所有由 GC Root 触发的可达对象。此时,所有未被标记的对象就是垃圾对象。之后在清除阶段,清除所有未被标记的对象。标记清除算法最大的问题就是空间碎片问题。如果空间碎片过多,则会导致内存空间的不连续。虽说大对象也可以分配在不连续的空间中,但是效率要低于连续的内存空间。
2.2、复制算法(Copying)
复制(Copying)算法。复制算法的核心思想是将原有的内存空间划分为大小相等的两块,每次只使用一块,在垃圾回收时,将正在使用的内存中的存活对象复制到未使用的内存块中。之后清除正在使用的内存块中的所有对象,之后交换两个内存块的角色,完成垃圾回收。复制算法的缺点是要将内存空间折半,极大地浪费了一半内存空间。因此现在的商业虚拟机都使用这种复制算法来进行新生代的垃圾收集!因为在对象存活率高的时候,复制算法就显得效率低下
2.3、标记-整理算法(Mark-Compact)
关于标记-整理算法还有一种叫法是标记压缩算法,知道其说的同一者就好了。
标记整理算法。标记整理算法可以说是标记清除算法的优化版,其同样需要经历两个阶段,分别是:标记阶段、整理阶段。在标记阶段,从 GC Root 引用集合触发去标记所有对象,和标记清除算法中的标记阶段是一样一样的。在整理阶段,其则是将所有存活的对象整理在内存的一边,之后清理边界外的所有空间。因此,标记-整理算法(Mark-Compact)不会产生内存碎片,但是会多花点时间用在整理(Compact)上面!
2.4、分代收集算法(Generational Collection)
“分代收集”(Generational Collection)算法,把Java堆分为新生代和老年代,这样就可以根据各个年代的特点采用最适当的收集算法。在新生代中,每次垃圾收集时都发现有大批对象死去,只有少量存活,那新生代选用复制算法,只需要付出少量存活对象的复制成本就可以完成收集。而老年代中因为对象存活率高、没有额外空间对它进行分配担保,老年代就使用“标记-清理”或“标记-整理”算法来进行回收。
2.5、四种回收算法总结
标记清除算法
分为标记阶段和清除两阶段。标记清除算法最大的问题就是空间碎片问题。比较适合在存活对象比较多的情况。
复制算法(Copying)
复制算法的缺点是浪费了一半内存空间。现在的商业虚拟机都使用这种复制算法来进行新生代的垃圾收集!因为在对象存活率高的时候,复制算法就显得效率低下比较适合存活对象比较少的情况。
标记整理算法(Mark-Compact)
标记整理算法是标记清除算法的优化版,标记-整理算法(Mark-Compact)不会产生内存碎片,但是会多花点时间用在整理(Compact)上面!
分代收集算法(Generational Collection)
新生代选用复制算法,老年代使用“标记-清理”或“标记-整理”算法来进行回收。
3、垃圾回收算法小结
借用大佬整理的一张图:
如果本文对你有一点点帮助,那么请点个赞呗,谢谢~
最后,若有不足或者不正之处,欢迎指正批评,感激不尽!如果有疑问欢迎留言,绝对第一时间回复!
欢迎各位关注我的公众号,里面有一些java学习资料和一大波java电子书籍,比如说周志明老师的深入java虚拟机、java编程思想、核心技术卷、大话设计模式、java并发编程实战.....都是java的圣经,不说了快上Tomcat车,咋们走!最主要的是一起探讨技术,向往技术,追求技术,说好了来了就是盆友喔...
这货到底还是不是垃圾?【垃圾回收GC算法JVM篇四】的更多相关文章
- JVM虚拟机垃圾回收(GC)算法及优缺点
一.什么是GC GC是jvm的垃圾回收,垃圾回收的规律和原则为: 次数上频繁收集新生区(Young) 次数上较少收集养老区(Old) 基本上不动永久区(Perm) 二.GC算法(分代收 ...
- JVM—垃圾回收GC算法
1 GC算法简介 算法 特点 标记-清除 分为"标记"和"清除"两个阶段 复制 可以解决效率问题,将可用的内存按容量划分为大小相等的两块. 标记-整理 先标记. ...
- jvm-垃圾回收gc简介+jvm内存模型简介
gc是jvm自动执行的,自动清除jvm内存垃圾,无须人为干涉,虽然方便了程序员的开发,但同时增加了开发人员对内存的不可控性. 1.jvm内存模型简介 jvm是在计算机系统上又虚拟出来的一个伪计算机系统 ...
- JVM学习——垃圾回收GC(学习过程)
JVM学习-垃圾回收(GC) 2020年02月19日06:03:56,开始学习垃圾回收,学习资料来源(张龙老师的JVM课程) JVM内存数据区域知识复习 学习垃圾回收之前,要对JVM内部的内存区域有详 ...
- golang 垃圾回收 gc
http://ruizeng.net/golang-gc-internals/ 摘要 在实际使用go语言的过程中,碰到了一些看似奇怪的内存占用现象,于是决定对go语言的垃圾回收模型进行一些研究.本文对 ...
- .NET垃圾回收(GC)原理
作为.NET进阶内容的一部分,垃圾回收器(简称GC)是必须了解的内容.本着“通俗易懂”的原则,本文将解释CLR中垃圾回收器的工作原理. 基础知识 托管堆(Managed Heap) 先来看MSDN的解 ...
- 从C#垃圾回收(GC)机制中挖掘性能优化方案
GC,Garbage Collect,中文意思就是垃圾回收,指的是系统中的内存的分配和回收管理.其对系统性能的影响是不可小觑的.今天就来说一下关于GC优化的东西,这里并不着重说概念和理论,主要说一些实 ...
- 垃圾回收GC:.Net自己主动内存管理 上(一)内存分配
垃圾回收GC:.Net自己主动内存管理 上(一)内存分配 垃圾回收GC:.Net自己主动内存管理 上(一)内存分配 垃圾回收GC:.Net自己主动内存管理 上(二)内存算法 垃圾回收GC:.Net自己 ...
- Java 类加载机制 ClassLoader Class.forName 内存管理 垃圾回收GC
[转载] :http://my.oschina.net/rouchongzi/blog/171046 Java之类加载机制 类加载是Java程序运行的第一步,研究类的加载有助于了解JVM执行过程,并指 ...
随机推荐
- 和35岁刘阿姨一起自测 Python 流程控制基本功
0.突然降临的困惑 流程控制语句.布尔值.布尔值操作符都属于 python 的基础功.大好周末我写这篇笔记,不是为了整理这些基础知识点,而是记录几个令我突然迷惑的代码段.--代码本身很简单,但即便已经 ...
- [考试反思]1027csp-s模拟测试90:自我
其实这套题很好. 但是这次,在T1爆炸的同时,T2和T3并没有出现能弥补的表现. 在AK仍然存在的同时,我居然连一个AC都没有. 所以最后就是一无是处的一场. 考试结束前估分:100+100+30=2 ...
- strGame:博弈论,trie
挺有意思的一道题.初探博弈论. 最好自己思考? 我们先考虑只有1轮游戏的情况. 这题明显要在字符串上一位一位地走,所以对字符串建立起trie. 最终建立起的trie的叶节点就是必败位置了. 对于非叶节 ...
- permu 莫队 总结
由于每次询问静态区间里完整值域段的最大大小 貌似很好用莫队转移,所以考虑怎么转移 当给它扩展一个数时,就是给值域添加了一个值 这个值可能已经存在,也可能是新的 有的神仙做法是维护了一个并查集,然而我这 ...
- 使用Typescript重构axios(六)——实现基础功能:获取响应数据
0. 系列文章 1.使用Typescript重构axios(一)--写在最前面 2.使用Typescript重构axios(二)--项目起手,跑通流程 3.使用Typescript重构axios(三) ...
- python——自行实现sorted函数
仿照内建函数sorted,自行实现一个sort函数,能够为列表进行排序 看下面实例的前提是掌握 0.掌握sorted函数的用法.1.函数基本概念.2.函数是如何传参的.3.掌握三元表达式.4.掌握内建 ...
- kubernetes的ingress-nginx
这是一篇学习记录.记录kubernetes集群中如何将jenkins服务通过域名接入外部.由于是测试环境,域名是自定义的,解析写在/etc/hosts和自己本地的hosts中. 部署图: 一.部署后端 ...
- nowcoder 鹏
鹏 时间限制:C/C++ 2秒,其他语言4秒空间限制:C/C++ 262144K,其他语言524288K 64bit IO Format: %lld 题目描述 化而为鸟,其名为鹏.鹏之背,不知其 ...
- tar使用笔记
解压到指定目录 -C tar -zxvf test.tar.gz -C /opt
- JMeter从0开始-笔记
1.安装Jmeter之前 安装Jmeter之前需要先配置Java环境,我们下载的是jmeter4.0,所以java版本最好是选用java8以上的版本. 安装JDk1.6的步骤如下: 点击下载的JDK文 ...