打开GC的大门
举个例子:在以前,我们大部分人都需要手动处理生活垃圾,把它包在一个大大的黑黑的袋子里面,或者直接上桶,然后”悲催“的自己拎着它,找到最近的垃圾点,扔进去,然后大功告成,可以回家吃饭了。
记住这里面的一些关键词:垃圾、大部分人、手动 、拎着垃圾去垃圾点扔
但是还有一种情况,想必大家也知道:生活中总有那么些人,拎着垃圾随便到处扔;甚至有些人不扔,就放在原地。
这里面,我们需要记住的关键词是:垃圾、有些人、乱扔甚至不扔
那么问题来了:
第一种情况下:我们需要自己判断什么是生活垃圾、并把这些垃圾手动打包、找到指定的地方处理掉它。(当达到一定量时,我们会发现,好累哦,而且还间接的影响了自己的工作,得不偿失,还不得不做,苦逼)
第二种情况下:管你什么是什么不是,我认为是的就是垃圾(所以会导致什么后果呢,今天刚买的衣服,mmp,还没穿了,下午就被认为是垃圾处理掉了)、管你什么地方能丢什么地方不能丢,我认为能丢就能丢(乱认垃圾)、一直放那不管它,我嚣张我任性(不扔)。(不怎么会耽误自己的工作,但对环境却影响很大,甚至最终还是会影响到自己)
那如果我们不处理这些垃圾会怎么样?乱处理又会怎么样?想必读者也肯定知道结果,这里便不再一一述说了!
怎么处理了?
把工作更加细分化。我们有了清洁工这类可爱的职业,我们只需把垃圾打包好,这些清洁工便会在适当的时候帮我们处理掉;甚至在某些情境下,这些清洁工自己就可以辨认什么是垃圾,帮我们清理掉。
这样的好处是什么了?
我们自己更加轻松,不用关心这些琐屑的事情了。
不会影响我们工作,提高了我们自己工作的效率。
而对于清洁工,它们也是一份职业,更有效的利用了社会资源。
同样的,在计算机的世界里,也有这样的概念存在。
例如:在老式的C/C++程序中,程序员定义了一个变量,就是在内存中开辟了一段相应的空间来存值。更何况,C提供动态申请空间,当用到某些特殊的数据结构时,不得不动态申请空间(不细谈语言特性)。由于内存是有限的,所以当程序不再需要使用某个变量的时候,该变量就充当了垃圾的角色,我们需要清除它,就需要销毁该对象并释放其所占用的内存资源,好重新利用这段空间。
变量不会再用 —> 垃圾
计算机内存是有限的—>程序员需要手动清除掉这些垃圾
那么问题又来了:
在C/C++中,释放无用变量内存空间的事情需要由程序员自己来处理。就是说当程序员认为变量没用了,就手动地释放其占用的内存。
但是这样显然非常繁琐,如果有所遗漏,就可能造成资源浪费甚至内存泄露。了解C的人可能都知道,你不仅必须精准的判断你所释放的空间是不是非法空间,还得知道该空间资源已经是垃圾了。
当软件系统比较复杂,变量多的时候,程序员往往就忘记释放内存或者在不该释放的时候释放内存了。(释放掉了还在用的资源,例如扔了刚买的衣服)
后果会很严重,那怎么解决了?
GC由此而诞生了!这个神秘的扫地老僧就此慢慢映入世人的眼中!
什么是GC
GC 是 Garbage Collection 的简称,中文称为“垃圾回收”。
垃圾具体指的是什么呢?
在现实生活中,垃圾具体指的是什么,想必大家也很清楚,可以理解为那些以后自己不会再用到的东西;
在GC中,垃圾的范畴也是如此。GC 把程序不会再用到的内存空间视为垃圾。
GC充当什么角色呢?
GC就相当于一个扫地大僧,他负责把院子扫干净,是一个默默无闻的清洁工。但是,大家都知道,天龙八部中的扫地大僧有多厉害,GC也是如此。
GC 要做的有两件事:
- 找到内存空间里的垃圾
- 回收垃圾,让程序员能再次利用这部分空间
你可以理解为,GC老僧,需要找到院子内所有的垃圾,然后把它们打扫干净,以备院子留有空地,给其它小僧使用。
有了GC,程序员就不需要再手动的去控制内存的释放。
回谈GC的历史
网上大部分人认为,GC 因为 Java 的发布而一举成名。当然,事实也是如此,不可否认,Java把GC推向了高潮!
我想大家大部分都是因为学习过Java或者其它编程语言,才了解到的GC。也会有人刚开始认为这种技术,是这门编程语言衍生、诞生出来的,也会有很多人可能会认为 GC 是最近才有的技术。
但是,其实GC是一门单独的、且古老的技术!GC 有着非常久远的历史,最初的 GC 算法是 John McCarthy 在 1960 年发布的。
John McCarthy 为 Lisp 之父、人工智能之父和GC 之父。
1960 年,McCarthy 在其论文中首次发布了 GC 算法。也就是我们所说的GC标记-清除算法!
为什么使用GC
在没有 GC 的世界里:
申请内存尚不存在什么问题,但在释放不要的内存空间时,就必须一个不漏地释放。这非常地麻烦。
如果忘记释放内存空间,该内存空间就会发生内存泄露 ,即无法被使用,但它又会持续存在下去。如果将发生内存泄露的程序放着不管,总有一刻内存会被占满,甚至还可能导致系统崩溃。
另外,在释放内存空间时,忘记初始化该指向的指针(为该指针赋null),这个指针就会一直指向释放完毕的内存空间。
因为这个指针没有指向有效的内存空间(因为释放内存空间后,该内存空间便归系统所拥有和分配,但指针却没有初始化,还是指向了这),处于一种悬挂的状态,所以我们称其为“悬垂指针”。
如果在程序中错误地引用了悬垂指针,就会产生无法预期的 BUG。因为你访问了系统还没有跟你分配的内存空间。
此外,悬垂指针也会导致严重的安全漏洞。懂技术的人,会通过利用这个悬挂指针访问事先注入到计算机恶意脚本的内存空间,执行恶意脚本,达到破坏、攻击计算机的效果。
更有甚者,还可能会出现错误释放了使用中的内存空间的情况。一旦错误释放了使用中的内存空间,下一次程序使用此空间时就会发生故障。大多数情况下会发生段错误,运气不好的话还可能引发恶性 BUG。
为了省去上述手动内存管理的麻烦,人们钻研开发出了 GC。
如果把内存管理交给计算机,程序员就不用去想着释放内存了。在手动内存管理中,程序员要判断哪些是不用的内存空间(垃圾),留意内存空间的寿命。
但只要有 GC 在,这一切都可以交给 GC 来做。有了 GC,程序员就不用再去担心因为忘了释放内存等而导致 BUG,从而大大减轻了负担。
也不用再去头疼费事的内存管理。GC 能让程序员告别恼人的内存管理,把精力集中在更本质的编程工作上。
想必到这里,大家都知道了GC带给我们的好处了。