这是我参与「第五届青训营 」伴学笔记创作活动的第 5 天。今天笔记的内容是自动内存内存管理。
重点内容
学习自动内存管理的基本概念与三种内存管理策略
主要知识点
一、自动内存管理
基本概念
程序在运行时需要根据需求动态分配内存,这部分内存称之为动态内存。我们最常见的分配动态内存的函数就是malloc()。
由此,我们可以引出自动内存管理的概念,即由程序语言的运行时系统管理动态内存,使用自动内存管理有以下两个优点
- 避免手动内存管理,提升程序员的时间利用率
- 保证内存使用的正确与安全
而一个合格的自动内存管理系统应当能够执行以下三个任务
- 为新对象分配空间
- 找到存活对象
- 回收死亡对象的内存空间
相关概念
- Mutator:业务线程,分配新对象,修改对象指向关系
- Collector:GC线程,找到存活对象,回收死亡对象的内存空间
- Serial GC:只有一个collector
- Parallel GC:支持多个collectors同时回收的GC算法
- Concurrent GC:支持Mutator与Collector同时执行
二、追踪垃圾回收
在编程的语境下,垃圾回收就是指回收不在使用对象所占的内存空间。而衡量一个对象是不是垃圾,有一个关键条件,即对象可不可达(或者说垃圾就是指针指向关系不可达的对象)
以下介绍追踪垃圾回收的基本方法
-
标记静态变量,全局变量,常量等根对象,这些对象只会在程序结束时才能被销毁
-
找到可达对象,一般使用的方法是求指针指向关系的传递闭包。而后将找到的可达对象也标记起来
-
在标记完不需要回收的对象后,对所有未被标记的不可达对象进行清理,而清理也分如下几步
- 将存活对象复制到另外的内存空间 - 将死亡对象的内存标记为“可分配” - 移动、整理存活对象
三、分代GC
分代假说
在我们的编程实践中,有很多对象在被分配后很快就不再使用了,在这个基础上出现了分代假说,即许多对象在很“年轻”的时候就会死亡(most objects die yound)。其中,我们通常用经历过的GC次数表示对象的年龄。
具体策略
基于分代假说,我们可以针对年轻和老年对象制定不同的管理策略
对于年轻代
- 对象分配采取常规策略
- 使用copying collection
- GC吞吐率很高
对于老年代
- 对象存活时间长,不应反复复制
- 采用,mark-sweep collection
引用记数
引用记数策略中,每个对象都有一个引用次数,只有引用次数大于0的对象是存活对象。
这一策略具有以下优点
- 内存管理操作被平摊到执行过程中
- 内存管理无需了解runtime细节
策略的缺点也很明显
- 维护引用次数会有额外开销
- 无法回收环形数据结构
- 内存开销大
- 回收内存是可能引发暂停
总结
今天笔记记录了自动内存管理的基本概念,同时介绍了三种常见的自动内存管理策略及其优劣。充分了解程序语言的自动内存管理机制对提高工程项目的效率有重要意义。