今天来聊聊JVM中的GC机制
什么是jvm?
答:虚拟机
什么是GC
答内存回收机制
那么接下来我们用Java来简单说明一下Java中的虚拟机的内存回收机制到底是怎么样的。
众所周知,Java是具有自动内存回收的,不等同于C,还需要程序猿考虑什么时候去回收该资源,虽然说更灵活。但是无异于加大了程序开发的负担。
那么我们知道了Java是“自动化”的,为啥还要了解他呢?
开发经验足的朋友都有过内存溢出之类的经历,但是我们却对他没有办法?在你了解GC之前肯定是这样的,之后,就不一定了。
GC实现发生是在虚拟机内存中的,细致一点来说在堆内存区域。
那么再细分来说可以说,GC分别对待三种数据内存:年轻代、老年代、永久代。
那么都这样说了,那就是表明它对待不同对象有不同的处理方案。
这里我们就长话短说了:
新生代:采用的是复制算法,简单来说,就是将一片内存中还存活的数据对象,挨个复制到另一个内存片中取,这样我们是不是可以理解为,在一个鸭棚,有天老板抓了20只鸭子杀了吃了,那么假设鸭棚的鸭子都不会动哈,那么鸭棚肯定会多出好多个空位(也就是内存碎片)。这个时候我们采用复制算法,将鸭棚A的鸭子一只只赶到鸭棚B(鸭棚B刚好容量为剩余鸭子的数量)这个时候,我们就可以对内存进行回收处理了。那么弊端也就很明显了,就是你要想回收内存,必须要是一个养鸭大户,每个内存片都要有对应的鸭棚B。
老年代:采用的是标记-清除算法,就是将标记中的内存片然后清除,比如老板今天发现五只鸭子死掉了,并且他们的羽毛上都有一个红点标记着,这个时候,老板进鸭棚直接提走丢掉这五只鸭子了。这种回收算法了,就可以快速的把不用的内存片清理回收了,但是你想,这样直接把标记的鸭子踢出去,那么肯定有好多个空位,这个时候是不是很多内存碎片,那么这个时候我们衍生出一种新的算法“标记-压缩-清除算法”,这个时候,你踢出鸭子后,然后我们再对内存片进行一个压缩操作,这个时候就对内存碎片进行一个去除了。
那么还有一种比较早出现的回收算法,引用计数算法,顾名思义,就是:对象被引用的数量进行清查,如果该对象被引用数量为0,那么就可以对该对象进行一个回收操作了。鸭棚里,如果这个鸭子是一个孤儿,没有子女,那么这个时候就可以把这个鸭子拉出去炖了,如果这个鸭子有个配偶,那么这个鸭子就可以存活。但是有个问题:如果鸭子A是鸭子B的父亲,那么鸭子B又是鸭子C的老婆,如果鸭子C又是鸭子A的儿子,那么这个时候就形成了一个回环死锁,那么对于这3只鸭子都不会被炖掉,这样的bug是不方便解决的。这也是引用计数的弊端,那么官方也表示了此弊端不好解决,所以也不是很流行。
那么对于GC机制,可以简单的以上所述了,至于高级的其他部分,我们可以在别的文章中聊聊。