热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

常见软件的GC算法解析

今天和大家一起解析下常见的GC算法设计。什么是GCGC是一种软件进行自动的内存回收的方式。如果软件运行过程中,发现某些对象没有了引用(或者称之为不可达)的状态时,就会启动GC过程。

今天和大家一起解析下常见的GC算法设计。


什么是GC

GC是一种软件进行自动的内存回收的方式。

如果软件运行过程中,发现某些对象没有了引用(或者称之为不可达)的状态时,就会启动GC过程。将这部分内存进行释放。以避免程序员因为忘记显示释放内存导致程序出现out of memory。

GC的过程

GC的过程主要分为标记、移动和压缩

标记

软件先分析堆中的所有内存对象,判断是否“存活”。

如果一个对象没有保持着被其他存活对象引用,就需要被清理

移动

将标记为存活的对象移动到另一个内存空间(老生代)

压缩

由于内存清理之后会出现很多碎片(非连续的小段可用内存),因此往往需要对其进行移动,确保大块的内存可用空间。(有时候移动和压缩会放在一起操作)

常见软件的GC算法解析

GC算法分析

为什么GC时要移动对象至另一空间

这里我们先思考一个问题,为什么需要把存活的对象移动到另一个内存空间。

首先,GC是一个非常耗性能的过程。

因为在GC过程中,你的程序中各个对象的引用指向的内存地址可能发生改变。

常见软件的GC算法解析

如果此时你仍然在执行程序,就可能访问到错误的内存地址。

因此GC期间会挂起程序的执行,也就是我们俗称的Stop the world。

在这一个限制下,我们设计GC算法的时候,必须做到尽可能少的进行GC

如何才能尽可能少的进行GC呢?

我们每次GC时,尽可能保证扫描的对象最大比例的释放内存。这样可用内存越多,触发GC的次数就会越少。

OK,我们再引进一个社会工程学知识,就是越新创建的对象,被清理的概率越高。

如果一个对象经过了一次GC,仍然存活了下来,那么它很有可能再下一次GC中存活。

那么将其放在一个单独的内存空间(老生代)中,可以有效的减少这些长生命周期对象的GC次数。

而仅对这些新生成的对象(新生代)进行GC,可以使用更少的对象扫描,完成近似相当的内存释放。

只有当老生代的内存空间也满了,才会进行老生代的GC。

常见软件的GC算法解析

老生代对象移动到哪里?

我们再思考一下,如果老生代也满了,那么GC时内存对象还能移动到哪里去呢?

在开一个“老老生代”?那“老老生代”也满了呢?

我们当然不能无限的开辟这么多的内存空间,放置GC存活的对象,这样内存的有效使用率太低了。

这里我们会在原始的老生代内存空间直接移动对象,将那些被回收的对象产生的内存碎片压缩即可。

常见软件的GC算法解析

.NET的GC设计

.NET的GC设计很简单,就同我们刚刚分析的情况基本一致。

它将内存分为三个区域,第0代,第1代,第2代。

所有的新对象的内存会分配至第0代。

当第0代满了,触发GC将第0代清空,将存活对象提升至第1代。

当第1代满了,再存活对象提升至第2代。

当第2代满了,GC后的存活对象直接在第2代的空间进行碎片压缩。

V8的GC设计

在.NET的GC设计中可能会出现这种情况,在第0代GC过程中,最新生成的内存对象被提升到了第1代中。

但是这些对象很可能是一些短生命周期的对象,仅仅是“偶然”在GC之前生成罢了。

但是这些对象被提升至第1代之后,很可能在之后的多次GC中,都不能被清理。

这些“无用”的内存占用就会消耗我们软件的内存空间。

V8 采用了另一种设计思想。

V8仅有新生代和老生代两个空间,并且它将新生代分成了From和To两个半空间。

每次新对象直接生成在From半空间内。

当触发GC时,From半空间内存活的对象被移动到To半空间内。

然后令To成为新的From半空间,From成为新的To半空间,即“半空间翻转”

在下一次GC时,检查GC存活对象,如果已经经历了一次GC,那么提升至老生代,否则还是移动到To半空间。

常见软件的GC算法解析

在V8的这种设计下,对象必须经历2次GC后才能提升到老生代。

避免了因为生成时机问题,导致内存中的“生命周期”延长。

JVM的GC设计

V8半空间的设计也会带来的一个问题就是,新生代的内存可用空间只有一半。

那么有没有什么方式可以增加一些空间呢?

JVM设计GC时将新生代分成了三块,eden,s0和s1(From幸存空间,To幸存空间)。

所有的对象创建时,内存分配至eden区域。

而当第一GC时存活对象提升至s0区域(From幸存空间)。

再下一次GC时,会将eden和s0一起进行GC,并且将存活对象移动至s1区域(To幸存空间)。

然后和V8一样s0和s1,发生“幸存空间翻转”

常见软件的GC算法解析
仅当对象在幸存空间存活超过了8次,才提升至老生代。

这种设计基于如下现实:每次GC仅有少部分对象存活。

因此JVM就将需要进行翻转的半空间缩小了,这样就能有更大的空间用于新对象内存分配。

后记

这里我们分析了.NET,V8和JVM的GC设计,但是并不是说明那种软件的GC算法更好,所有的算法架构都是进行一种设计取舍。

我们需要知道大部分情况下,GC能够直接帮我们处理内存问题。

而在那些内存敏感的应用场景,期望依赖某一软件的GC设计原生机制来自动处理,也是不会奏效的。


参考文档:

  • Java Garbage Collection Basics
  • 垃圾回收 (计算机科学) - ***,***的百科全书
  • JVM 垃圾收集与 GC 算法 - 简书
  • GC的三大基础算法 - code-craft - SegmentFault 思否
  • Java虚拟机详解04----GC算法和种类【重要】 - 千古壹号 - 博客园
  • Understanding the Java Memory Model and Garbage Collection - DZone Java
  • 垃圾回收的基本知识 - Microsoft Docs

本文会经常更新,请阅读个人博客原文: https://xinyuehtx.github.io/ ,以避免陈旧错误知识的误导,同时有更好的阅读体验。

常见软件的GC算法解析 本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。欢迎转载、使用、重新发布,但务必保留文章署名黄腾霄(包含链接: https://xinyuehtx.github.io/ ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请 与我联系 。


推荐阅读
  • Android中高级面试必知必会,积累总结
    本文介绍了Android中高级面试的必知必会内容,并总结了相关经验。文章指出,如今的Android市场对开发人员的要求更高,需要更专业的人才。同时,文章还给出了针对Android岗位的职责和要求,并提供了简历突出的建议。 ... [详细]
  • [译]技术公司十年经验的职场生涯回顾
    本文是一位在技术公司工作十年的职场人士对自己职业生涯的总结回顾。她的职业规划与众不同,令人深思又有趣。其中涉及到的内容有机器学习、创新创业以及引用了女性主义者在TED演讲中的部分讲义。文章表达了对职业生涯的愿望和希望,认为人类有能力不断改善自己。 ... [详细]
  • 如何用UE4制作2D游戏文档——计算篇
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了如何用UE4制作2D游戏文档——计算篇相关的知识,希望对你有一定的参考价值。 ... [详细]
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
  • Java验证码——kaptcha的使用配置及样式
    本文介绍了如何使用kaptcha库来实现Java验证码的配置和样式设置,包括pom.xml的依赖配置和web.xml中servlet的配置。 ... [详细]
  • 本文讨论了在手机移动端如何使用HTML5和JavaScript实现视频上传并压缩视频质量,或者降低手机摄像头拍摄质量的问题。作者指出HTML5和JavaScript无法直接压缩视频,只能通过将视频传送到服务器端由后端进行压缩。对于控制相机拍摄质量,只有使用JAVA编写Android客户端才能实现压缩。此外,作者还解释了在交作业时使用zip格式压缩包导致CSS文件和图片音乐丢失的原因,并提供了解决方法。最后,作者还介绍了一个用于处理图片的类,可以实现图片剪裁处理和生成缩略图的功能。 ... [详细]
  • 本文介绍了OkHttp3的基本使用和特性,包括支持HTTP/2、连接池、GZIP压缩、缓存等功能。同时还提到了OkHttp3的适用平台和源码阅读计划。文章还介绍了OkHttp3的请求/响应API的设计和使用方式,包括阻塞式的同步请求和带回调的异步请求。 ... [详细]
  • 2018年人工智能大数据的爆发,学Java还是Python?
    本文介绍了2018年人工智能大数据的爆发以及学习Java和Python的相关知识。在人工智能和大数据时代,Java和Python这两门编程语言都很优秀且火爆。选择学习哪门语言要根据个人兴趣爱好来决定。Python是一门拥有简洁语法的高级编程语言,容易上手。其特色之一是强制使用空白符作为语句缩进,使得新手可以快速上手。目前,Python在人工智能领域有着广泛的应用。如果对Java、Python或大数据感兴趣,欢迎加入qq群458345782。 ... [详细]
  • 使用在线工具jsonschema2pojo根据json生成java对象
    本文介绍了使用在线工具jsonschema2pojo根据json生成java对象的方法。通过该工具,用户只需将json字符串复制到输入框中,即可自动将其转换成java对象。该工具还能解析列表式的json数据,并将嵌套在内层的对象也解析出来。本文以请求github的api为例,展示了使用该工具的步骤和效果。 ... [详细]
  • Google Play推出全新的应用内评价API,帮助开发者获取更多优质用户反馈。用户每天在Google Play上发表数百万条评论,这有助于开发者了解用户喜好和改进需求。开发者可以选择在适当的时间请求用户撰写评论,以获得全面而有用的反馈。全新应用内评价功能让用户无需返回应用详情页面即可发表评论,提升用户体验。 ... [详细]
  • 自动轮播,反转播放的ViewPagerAdapter的使用方法和效果展示
    本文介绍了如何使用自动轮播、反转播放的ViewPagerAdapter,并展示了其效果。该ViewPagerAdapter支持无限循环、触摸暂停、切换缩放等功能。同时提供了使用GIF.gif的示例和github地址。通过LoopFragmentPagerAdapter类的getActualCount、getActualItem和getActualPagerTitle方法可以实现自定义的循环效果和标题展示。 ... [详细]
  • 闭包一直是Java社区中争论不断的话题,很多语言都支持闭包这个语言特性,闭包定义了一个依赖于外部环境的自由变量的函数,这个函数能够访问外部环境的变量。本文以JavaScript的一个闭包为例,介绍了闭包的定义和特性。 ... [详细]
  • 本文介绍了在Windows环境下如何配置php+apache环境,包括下载php7和apache2.4、安装vc2015运行时环境、启动php7和apache2.4等步骤。希望对需要搭建php7环境的读者有一定的参考价值。摘要长度为169字。 ... [详细]
  • 浏览器中的异常检测算法及其在深度学习中的应用
    本文介绍了在浏览器中进行异常检测的算法,包括统计学方法和机器学习方法,并探讨了异常检测在深度学习中的应用。异常检测在金融领域的信用卡欺诈、企业安全领域的非法入侵、IT运维中的设备维护时间点预测等方面具有广泛的应用。通过使用TensorFlow.js进行异常检测,可以实现对单变量和多变量异常的检测。统计学方法通过估计数据的分布概率来计算数据点的异常概率,而机器学习方法则通过训练数据来建立异常检测模型。 ... [详细]
  • 统一知识图谱学习和建议:更好地理解用户偏好
    本文介绍了一种将知识图谱纳入推荐系统的方法,以提高推荐的准确性和可解释性。与现有方法不同的是,本方法考虑了知识图谱的不完整性,并在知识图谱中传输关系信息,以更好地理解用户的偏好。通过大量实验,验证了本方法在推荐任务和知识图谱完成任务上的优势。 ... [详细]
author-avatar
吴玉占_717
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有