JVM简介(三)——GC

GC和内存模型一样,和实现有关。这里介绍的是一些基本原理以及hotspot的实现。java7还存在永久代,java8把永久代移除了。在最后一点有提到。
 
        一。基本概念

        1.堆区从运行分配的角度分为java堆(用于对象内存的分配)和方法区(类信息等)。但是从另一个

           视角,生命周期的角度,堆区分为年轻代、年老代、永久代。永久代即方法区。基本没有GC

 
        2.GC视角的堆区如下图(图转自csdn):
        JVM简介(三)——GC 
           年轻代分为:
                   Eden区
                   S0区(Survivor区1、from区)
                   S1区(Survivor区2、to区)
           年老代:一整块大区
           永久代:即方法区
 
        3.年轻代的GC叫minor GC。当年轻代空间不够时触发minor GC
           年老代的GC叫major GCfull GC。当年老代空间不够时触发major GC。现在一般的做法是,
           在进行major GC之前,先进行一次minor GC。把不需要的对象先清理掉,这样年老代相关对象也
           可能不需要了
 
        二。对象生命周期
 

Eden区

From区

To区

Old区

Perm区


        一般对象都被创建在Eden区(特别大的会直接创建在Old区)

 

        一次minor GC后仍存活的对象,会从Eden区被移到From区To区

        同样,From区会被移到To区或者To区会被移到From区

       (所以具体移到哪个区看当前情况,一次minor GC后,Eden区Survivor区中的某一个,一定是空的,一定是空的)

 

        当经过一定次数(默认15次)的minor GC后仍然存活的对象,会被移到Old区

 

        三。GC算法纬度

        串行GC——暂停应用程序线程,使用单CPU进行处理

        并行GC——暂停应用程序线程,使用多CPU,将任务分成多个子任务,并行处理 

        并发GC——不暂停应用程序线程,GC与应用程序并发处理

 

        四。GC算法

        图均转自CSDN

        1.标记清除(Mark-sweep)——先标记不用的后清除。但是效率低、会产生大量碎片

           JVM简介(三)——GC

 

        2.复制(Copying)——内存分两块区域,每次只使用一块区域,GC时把正在使用的(即不能

           被清除的)复制到另一块去。效率不错,且不会碎片化——需要两倍的空间

           JVM简介(三)——GC
 

        3.标记整理(Mark-Compact)——先标记不用的,然后压缩到一起。避免了碎片。

           JVM简介(三)——GC

 

        4.CMS——一般用于年老代

           CMS并非没有暂停,而是用两次短暂停来替代串行标记整理算法的长暂停,它的收集周期是这样:

                (1)初始标记(CMS-initial-mark):单线程,从GC Root寻找直达的对象,速度快,需暂停

                (2)并发标记(CMS-concurrent-mark):与应用线程一起运行,是CMS最主要的工作阶段,

                         通过直达对象,扫描全部的对象,进行标记

                (3)重新标记(CMS-remark):修正并发标记时由于应用程序还在并发运行产生的对象的修改

                         多线程,速度快,需要全局停顿

                (4)并发清除(CMS-concurrent-sweep):与应用程序一起运行

                (5)并发重设状态等待下次CMS的触发(CMS-concurrent-reset)。

 

           CMS为何采用清除而不是压缩? 

                CMS主要关注低延迟,因而采用并发方式,清理垃圾时,应用程序还在运行,如果采用压缩

                则涉及到要移动应用程序的存活对象,此时不停顿,是很难处理的,一般需要停顿下,移动存活

                对象,再让应用程序继续运行,但这样停顿时间变长,延迟变大 ,所以CMS采用清除算法。

 

        五。算法选择

        年轻代(Eden+Survivor To+Survivor From)使用复制(Copying)算法。可配置串行或并行。

        年老代使用标记整理(Mark-Compact)算法。可选择串行。可配置串行或并行。另可配置为使用CMS

 

        六。垃圾检测算法

        1.引用计数法——给一个对象添加引用计数器,每当有个地方引用它,计数器就加1;引用失效就减1。

 

                但是,如果我有两个对象A和B,互相引用,除此之外,没有其他任何对象引用它们,实际上这

                两个对象已经无法访问,即是我们说的垃圾对象。但是互相引用,计数不为0,导致无法回收

 

        2.可达性分析算法——以根集对象为起始点进行搜索,如果有对象不可达的话,即是垃圾对象。

           这里的根集一般包括java栈中引用的对象、方法区常良池中引用的对象、本地方法中引用的对象等。

 

        七。关于持久代

        Java8开始。持久代被移除了,改用Metaspace。底层存储应该还是堆,只不过分开管理,单独的

        内存分配单独的GC等。脱离开JVM调优范围。

posted @ 2018-03-16 16:40  架构之美,智慧之光  阅读(210)  评论(0编辑  收藏  举报