今日分的学习内容——垃圾回收机制(GC)
算是一个比较基础的内容,但是以前一直没有时间系统的学习这一方面,今天就全面的来学习学习。由于Java语言的垃圾回收机制做的比较完善,就拿Java来说明了 。
- 为什么要进行垃圾回收?
世上本没有GC,用C/C++的人多了,也就有了垃圾回收——鲁迅。
很明显,一开始的语言都是没有GC机制的,全靠程序员自己来管理内容,啥时候分配了空间,就得记得还给操作系统。虽然这样对于一些大神来说可以写出高效的程序,少用内存,但是对于大部分程序员来说还是太麻烦了,于是就想着语言自己给我把不用的内存给回收就好了,也就有了后来的事情。 - 该怎么实现呢?
想法很美好,但是要怎么做呢?
- 第一版本V0.1——引用计数
前辈们首先想到的就是,对于每一个对象设置一个引用计数,如果没有人对这个对象有引用了,也就不会有人用了,就可以释放了(很像操作系统中对于打开文件的做法)。
相信很多人都能想到这个,前辈们也就这样做了。这个朴素的算法很容易实现,而且对于程序的运行速度来说也没有降低很多,感觉还可以。但是用着用着问题又出来了。这个问题的产生和内存的管理有关系。假设我们在一片连续的内存中声明了几个对象,中间的几个对象被释放了,这些空出来的内存很碎片化,操作系统很难利用得上,释放也就没有了意义。 - 改进版本V1.0——节点复制
于是我们可以做的就是把内存一分为二,一块不用,一块随便用。设定一个闹钟,时间一到,把这边的内存中的东西集体复制到另一半中,顺带还整理了内存(连成片了),一举两得 。想法很简单,实现也不是很难,前辈们就又用了,大家也是挺满意的。
可是好景不长,程序员中的极致派觉得这也太浪费了,一半内存做备份(真家里有矿),还是得改改。 - 改进版本V2.0——标记-清扫
这一次还是使用引用的做法,我们把各个对象看做节点,这些节点加上它们之间的引用关系可以作为一棵树,我们从根节点开始遍历,如果到最后还有节点没有包括进来,这些节点就可以释放了。
根节点是一些没有父对象来生成的。 - 一些更高级的玩法——分代收集
为了使得垃圾回收更加有针对性,可以把不同的对象分成不同的等级——年轻代,老年代。一般老年代已经用了很久,一般还会继续用下去,年轻代的很可能马上就不用了。然后通过一定的机制完成代之间的转移就可以了。
其他一些GC相关的问题
- 一个通过make()命令创建的缓冲区被分配了一块内存后。如何销毁缓冲区并收回内存?
buffer = nil
;在运行时,buffer = nil将启动垃圾回收 - Java 中的StrongReference、 SoftReference、 WeakReference 以及 PhantomReference是啥?
StrongReference 是 Java 的默认引用实现, 它会尽可能长时间的存活于 JVM 内,当没有任何对象指向它时将会被GC回收。
WeakReference,顾名思义, 是一个弱引用, 当所引用的对象在JVM 内不再有强引用时, 将被GC回收。
虽然 WeakReference 与 SoftReference 都有利于提高 GC 和 内存的效率,但是 WeakReference ,一旦失去最后一个强引用,就会被 GC 回收,而 SoftReference 会尽可能长的保留引用直到 JVM 内存不足时才会被回收(虚拟机保证), 这一特性使得SoftReference 非常适合缓存应用
网友评论