G1的个人看法
G1作为一个垃圾回收算法,这几年特别火,从Java9开始,G1已经作为JVM的这个默认的回收器了,很多公司也都开始采用G1来做垃圾回收,我们都知道JVM的堆,会分成年轻代、老年代。年轻代又有eden区(Eden Space)、Survival1区、Survival2区(Survivor Space)。JVM产生的对象先会扔到eden区里面,然后按照存活的时长再移到Survival1区,Survival2区(或者叫from区、to区)最后会挪到old区里面,old区满了或者存不下,那就直接full GC了,这就是JVM垃圾回收器的默认处理方式,也就是所谓的分代收集。 不管你是CMS还是parallels。
绝大多数的JVM的回收器的本质都是采用这种分代收集的算法来处理的垃圾回收。
当然G1也不例外,但是它NB的地方是在于不再将整个堆的空间进行分代,什么年轻代、老年代分的很清楚然后去做物理隔绝,G1不是,它是将Java堆划分成多个大小相同的独立区域(region区域),这个区域可能之前是年轻代,后来进行垃圾回收,之后可能又变成老年代,也就是说区域的功能可能会动态的变化,不是说之前的是固定的区域。这种动态的好处,就是空间的利用会很好,哪里有空间呢,就可以拿来用,比较灵活,这是一个亮点,就是基于区块级的分代收集。
G1另一个亮点呢,是做空间的整合,有个专门的线程,来帮你处理内存区块,哪些都用过的,哪些没用的它会帮你自动的做统一的分类,用过的放在一起,没用的放在一起。这样的好处,就是为了减少内存的碎片,存方便取也方便,因为都在一起,这个对比CMS的话要高级很多,当然这些还不是最牛逼的,G1我认为最牛逼的点,是能够让用户设置应用的暂停时间,也就是可以去人为的设置full GC的时间,它选择一些内存块,而不是整代内存来回收,这个是G1跟其他GC不同的特点。其他的GC,可能每次回收都会去把整个的年轻代或者老年代做统一的回收,而回收内存所需要的时间,就取决于内存块的大小,以及实际垃圾的多少,所以垃圾回收的时间它是不可控的,而G1每次它不会去回收整个代的内存。那么它到底回收多少呢?看用户配置的暂停时间,配置的时间短,G1就少回收一点,配置时间长就多少回收一点,这就比较厉害了,如果你的服务器是大内存的话,本身来讲,你相对JVM的年轻代、老年代来说也就会比较大,如果采用G1的话呢,就能很好管控这个回收时间,因为你大内存的话,它本身回收时间是不可控的。
另外还有一点,是它对于大对象的处理,像我们传统的垃圾回收器,如果有一个大的对象过来,如果年轻代放不下,会直接放到老年代,那G1不是这样,它有一个叫homegos区,专门来存放这个大对象,还可以横跨多个region来存放。这样的好处就是能够避免对象太大直接进入老年代,如果直接进入老年代的话,那就加速了full GC的频率。(完)
ps: 如果有任何疑问,欢迎评论区给我留言
注意:本文归作者所有,未经作者允许,不得转载