作为 Java 语言最重要的特性之一的自动垃圾回收机制,也是基于 JVM 实现的。那么,自动垃圾回收机制到底是如何实现的呢?
1.GC是干啥的?
进行资源的回收
1.1.对于 C/C++ 而言
对于C/C++语言是没有GC机制的,对于内存的管理会比较麻烦,需要手动在合适的时机进行释放,而且一旦内存申请了没有释放,当我们后面程序再次申请内存的时候,发现内存已经被占用了,那么就会导致“内存泄漏”问题(非常严重),既然GC这么好那么问题来了~
①. 既然GC这么好,为什么C/C++使用GC呢?
俗话说的好:“世界上没有免费的午餐”,是需要成本滴~
- 首先资源付出的成本(CPU,内存……)支持垃圾回收机制能进行工作
- GC对于内存的回收即时性没有那么高(虽然能在一定的时间内进行回收,但也不是不用了立刻就回收,有一定的延迟)
- GC中存在一个致命的问题:STW问题(stop the word)
什么是STW问题?
就是当GC工作的时候,正常的业务代码可能无法执行,必须要等到GC工作完毕。对于服务器来讲,一旦服务器出发了GC,就可能导致正常代码无法执行(会出现卡顿),因为服务器可能会不断接收到请求,那么就会造成请求的积压,可能导致请求到一半就停止,或者是刚刚接收到请求而无法处理请求,直接造成用户体验的影响。
②. C/C++不是调用free/dalete函数就释放了吗?为什么还会出现“内存泄漏“问题?
答:上面提到需要在合适的时机进行释放,虽然内存内存的申请时机一般都是明确的,但是这个合适的释放时机是比较模糊的
1.2.对于 Java 而言
有GC机制,只管申请内存,无需关注内存的释放,而且可以很大程度上规避内存泄漏的问题(也不是完全没有)2.GC要回收哪些内存?
1.PC程序计数器 / 栈 :都不要 GC 回收,因为他的释放时机很明确,随着线程的创建而申请内存,随着线程的销毁而释放。
2.常量池 / 方法区 :GC也不需要太关心,因为它占用的空间比较小,数据也很少会失去作用,如果对其进行GC,回收内存的性价比也不高(比如:打扫一个干净的小房间,即便你在怎么去打扫,也扫不出多少灰尘)
3.堆:GC主要回收的区域,堆的内存区域也很大,申请又很频繁(因为每次new对象都会在堆上申请内存)