一、概述

垃圾收集Garbage Collection通常被称为GC,但是GC一般也指Garbage Collecting(垃圾回收这个动作)或Garbage Collector(垃圾回收器),这些都是是JVM知识体系中非常重要的知识,也是程序员必须要掌握的技能,本文将详细讲述Java垃圾回收的概念机制以及核心算法。

二、分析

1. 什么是垃圾

我们所说的垃圾是指没有任何引用的一个对象或者多个对象(这多个对象相互引用,但是没有一个与主对象挂钩,也就是根可达算法(下文会讲)无法找到这其中任何一个对象)。

我们再来来熟悉两个概念:

(1) 内存泄露:内存泄露是指有的内存地址太过碎片化而无法被利用,我们都知道一个对象创建的时候开辟的内存空间是连续的,所以太过碎片化的内存空间就没办法利用。内存泄露多了也会导致内存溢出。

(2) 内存溢出:内存溢出是指内存已经装满了,无法再装下更多的对象了。

C和C++都是需要开发者用代码手动回收内存的:C语言用free关键字来回收内存,C++用的是delete。但是手动回收内存容易出现两种类型问题:忘记回收(容易引发OOM内存泄露)和多次回收。

后来诞生的java、python等都是自带了垃圾回收器的语音,开发者只管创建对象,对象的销毁不需要手动处理,由专门的垃圾回收器进行回收。

2. 如何定位垃圾

常见的方式有两种:

(1) 引用计数(Reference Count):每当一块内存被一个对象引用,那么计数就+1,当没有对象指向时,计数为0,就表示这块内存可以被回收了,如下图:

但是引用计数没办法解决垃圾之间互相引用的情况,当几块内存都没有外部引用,但是这几块内存之间相互引用的时候,这几块内存也应该视为垃圾,但是引用计数却不为0,如下图:

(2) 根可达算法(Root Searching):当程序运行时,将根对象取出,由根对象出发往下查找,最终找不到的对象,都视为无法由根对象找到,也就是说找不到的对象就都视为垃圾。如下图:

那么哪些对象是根对象呢?主要包含:JVM stack,native method stack,run-time constant pool(运行常量池里的对象),static references in method area(方法区里的静态引用),Clazz等。

3. 常见的垃圾回收算法

主要包含以下3种:

(1) 标记清除(mark sweep):就是将找到的垃圾标记出来,然后直接清除掉。但是这种方式有一个严重的毛病,会使得内存变得碎片化,也就是有多个不连续的内存。

(2) 拷贝算法(copying):这种方式的做法就是将内存平分成两块,在使用的过程中只能在其中一块内存里创建对象,当需要垃圾回收时,将有对象的内存全部复制到另一边,并且将当前区域全部清除。这种方式解决了内存碎片化的问题,但是却浪费了空间,因为每次只能利用一半。

(3) 标记压缩(mark compact):这种方式就是在清理垃圾的同时,将同类型的内存空间放置在一起,也就是说在清理的同时进行空间整理,并且多线程时还需要进行线程同步,所以这种方式明显的缺点就是效率偏低。

常用的垃圾回收算法就是这3种或者这3种方式的组合。

4. JVM内存分代模型(用于分代垃圾回收算法)

JVM的内存模型是由垃圾回收器决定的,一般分为分代模型和不分代模型,两种内存模型不一样。分代垃圾回收的内存模型如下图:

分代模型在逻辑上分代,在物理层面也就是内存中也是分成了new(新生代)和old(老年代)两个大区域。新生代区又详细分为eden(伊甸园)、survivor1和survivor2。new(年轻代)的对象有两大特点:大量产生;大量回收(大多数情况下,一次回收90%的对象)。所以根据new年轻代的特点,采用的算法是Copying算法;而Old老年代则是采用标记压缩(mark compact)算法,以此保证内存的连续性 。

值得一提的是,new新生代和old老年代的比例默认是1:2。但是这个比例也是JVM调优中可以调节的参数,所以上图写的1:3。eden和survivor1,survivor2的默认比例是8:1:1,也是可以调整的。

为了方便对于分区的理解,我们由一个对象的创建到回收进行分析,分区内变化如下:

对象分配过程如下:

过程分析:

(1) 当我们new出一个对象,JVM会首先尝试往栈上分配,如果能够分配得下,就分配到栈上分配到栈上的对象有好处就是不需要GC进行管理,什么时候不需要用到此对象了,将对象出栈就可以了。但是分配到栈上的对象是有要求的:第一,对象比较小,因为栈空间本来就不够大;第二,对象比较简答。

(2) 如果栈上分配不下,我们就判断这个对象是不是够大,如果足够大就直接放在老年代区,在老年代区的对象经过一次全量垃圾回收FGC后,才有可能被回收掉。

(3) 如果如果栈上分配不下并且对象不大,就会判断对象能否被存在线程本地分配缓冲区-TLAB(Thread Local Allocation Buffer)。但是不管放不放得下,都是放在新生代区的伊甸区eden。 但是因为堆是共享的,多个线程可以同时创建对象就可能会争夺同一块内存区域,所以为了保证线程安全,Eden区又被分配成一个个线程本地分配缓冲区,这个TLAB是线程私有的,每个线程都有自己的TLAB,避免了多线程环境下使用同步技术带来的性能损耗。

(4) 伊甸区eden的对象在经过一次GC后,如果被回收掉了,那就结束了生命周期。

(5) 伊甸区eden的对象在经过一次GC后,如果没有被回收掉,JVM在整个new新生代区都采用Copying(拷贝算法),将不是垃圾的对象拷贝到幸存者区survivor1,对比上面的堆内存逻辑分区图。幸存者区survivor1中的对象再经过一次GC后如果对象还存活,那么就拷贝到幸存者区survivor2并且清理掉幸存者区survivor1中的所有对象,再有GC就反复这个操作,直到对象的分代年龄达到了移到老年代的界限(一般分代垃圾回收器默认是15,CMS默认是6),就会被移到老年代中,老年代采用标记压缩(mark compact)算法,保证内存的连续性 。

5. 常见的垃圾回收器

jdk从1.0到14.0一共诞生了10种垃圾回收器,如下图:

分类如下:

(1) 分代模型:Serial,Serial Old,Parallel Scavenge,Parallel Old,ParNew,CMS

(2) 不分代模型:G1(虽然物理模型上没分代,但是逻辑层面上是分代的,jdk1.8及以上的版本建议使用G1,响应时间很快,但是1.8默认是PSPO<Parallel Scavenge和Parallel Old>),ZGC(Oracle官方支持),Shenandoah(小红帽公司开发)

(3) 特殊模型:Epsilon(这种垃圾回收器不回收垃圾,只是跟踪垃圾的产生和回收,但是这个回收只是动作,其实没真正回收。Epsilon有两个用途:<1>用于调试;<2>内存很大,程序很小很快就能运行完成。)

6. 常见垃圾回收器组合参数设定

(1) -XX:+UseSerialGC = Serial New (DefNew) + Serial Old

小型程序默认情况下不会是这种选项,HotSpot会根据计算及配置和JDK版本自动选中收集器。

(2) -XX:+UseParallelGC = Parallel Scavenge + Parallel Old (jdk1.8默认)【PS+Serial Old】

(3) -XX:+UseParallelOldGC = Parallel Scavenge + Parallel Old

我们可以用命令行-XX:+PrintCommandLineFlags查看我们所使用的是哪种垃圾回收器,如下图:

三、总结

通过本文,我们了解了GC的基础概念、常用的垃圾回收算法、以及JVM内存分代模型和所有的垃圾回收器的特点,下一文我们将着重讲解不同垃圾回收器所采用的底层算法及原理,请期待《我的JVM(二):十种垃圾回收器所采用的底层算法及原理》。

更多精彩内容,敬请扫描下方二维码,关注我的微信公众号【Java觉浅】,获取第一时间更新哦!

http://weixin.qq.com/r/xx3v9_7EY7McraqU90jV (二维码自动识别)

根可达算法的根_我的JVM(六):GC的基础概念以及GC算法相关推荐

  1. 光流(optical flow)基础概念以及典型算法

    光流(optical flow)基础概念以及典型算法 文章目录 光流(optical flow)基础概念以及典型算法 什么是光流? 一.传统经典光流算法: Lucas-Kanade 二.基于神经网络的 ...

  2. grad在python什么模块_深度学习(Deep Learning)基础概念1:神经网络基础介绍及一层神经网络的python实现...

    此专栏文章随时更新编辑,如果你看到的文章还没写完,那么多半是作者正在更新或者上一次没有更新完,请耐心等待,正常的频率是每天更新一篇文章. 该文章是"深度学习(Deep Learning)&q ...

  3. 商城项目01 _电商系统基本模式、分布式基础概念、微服务架构图、微服务划分图

    文章目录 ①. 电商系统基本模式 ②. 分布式基础概念 ③. 微服务架构图详解 ④. 微服务划分图 ①. 电商系统基本模式 ①. B2C模式 就是我们经常看到的供应商直接把商品卖给用户,即" ...

  4. 麻将开金算法java代_中国麻将(Chinese Mahjong, UVa 11210)【JAVA算法实现】

    题目描述麻将是一个中国原创的4人玩的游戏.这个游戏有很多变种,但本题只考虑一种有136张牌的玩法.这136张牌所包含的内容如下.饼(筒)牌:每张牌包括一系列 题目描述 麻将是一个中国原创的4人玩的游戏 ...

  5. prim算法求最小生成树_最小生成树的两种方法(Kruskal算法和Prim算法)

    关于图的几个概念定义: 连通图:在无向图中,若任意两个顶点vivi与vjvj都有路径相通,则称该无向图为连通图. 强连通图:在有向图中,若任意两个顶点vivi与vjvj都有路径相通,则称该有向图为强连 ...

  6. python核心理念_《三天搞定Python基础概念之第一天》中文版

    前言: 首先,非常感谢Jiang老师将其分享出来!本课件非常经典! 经过笔者亲测,竟然确实只要三天,便可管中窥豹洞见Python及主要库的应用.实属难得诚意之作! 其次,只是鉴于Jiang老师提供的原 ...

  7. learnpythonthehardway中文版_《三天搞定Python基础概念之第一天》中文版

    前言: 首先,非常感谢Jiang老师将其分享出来!本课件非常经典! 经过笔者亲测,竟然确实只要三天,便可管中窥豹洞见Python及主要库的应用.实属难得诚意之作! 其次,只是鉴于Jiang老师提供的原 ...

  8. 最大流(网络流基础概念+三个算法)

    下面是由一道题引发的一系列故事... 题目链接 http://poj.org/problem?id=1273 Drainage Ditches Time Limit: 1000MS Memory Li ...

  9. pyqt5程序发生错误不中断_关于Windows页面错误的一些基础概念

    很少被开发者关注的页面错误 今天我们会说说关于虚拟内存处理中最为常见的一个问题:页面错误(Page Fault). 什么情况下会发生一个页面错误呢? 当应用程序请求的页面地址不在当前的内存驻留页面(M ...

最新文章

  1. WKWebView 那些坑
  2. MATLAB实现直方图均衡化与规定化
  3. 《现代操作系统》精读与思考笔记 第七章 多媒体
  4. android中多态的应用_动态代理原理及在 Android 中的应用
  5. JAVA NIO基础知识
  6. Intel缓存控制相关的寄存器
  7. ROS学习笔记四:理解ROS节点
  8. CSS如何实现数字分页效果
  9. 学习SpringBoot(1)入门及简单的配置
  10. 【Python实例第34讲】高斯过程分类:XOR数据集
  11. Out of resources when opening file './xxx.MYD' (Errcode: 24)
  12. 小说我成了机器人桑尼_我在月球当皇帝
  13. 【毕业设计】基于单片机的指纹识别考勤系统 - 物联网 stm32
  14. 整理电力系统GPS时间同步装置(GPS对时系统)孤岛方案
  15. Hadoop大数据技术课程总结2021-2022学年第1学期
  16. VBox下频繁出现0x00000000指令引用的0x00000000内存,该内存不能为written:解决方案(附文件)
  17. ionic3 使用QR Scaner 扫描
  18. PKI与证书相关基本知识
  19. 大型电商架构亿级流量电商详情页系统--实战 服务降级
  20. cogs 997. [東方S2] 射命丸文

热门文章

  1. Spring循环依赖的三种方式
  2. php与mysql手册下载地址_PHP与Mysql的连接
  3. 学.net还是php,ASP.NET和php哪个更容易学
  4. cognos报表导出excel_有了这个报表工具,一键生成自定义的各种报表,还可以导出Excel...
  5. java ajax jquery分页插件_jquery ajax分页插件的简单实现
  6. 常用并发工具类(锁和线程间通信工具类)
  7. 四年级计算机笔试题,四年级计算机考试卷.doc
  8. 万州哪里有维修服务器,网关可以设在服务器、微机或大型机上
  9. python转换窗口无响应_Tkinter窗口显示(没有响应),但代码正在运行
  10. xshell6 不更新无法使用_世纪金花商联卡无法正常使用 客服:因门店面临改造,涉及品牌、规则每天都在更新...