qileilove

          blog已經(jīng)轉(zhuǎn)移至github,大家請(qǐng)?jiān)L問 http://qaseven.github.io/

          JVM分代垃圾回收策略的基礎(chǔ)概念

           由于不同對(duì)象的生命周期不一樣,因此在JVM的垃圾回收策略中有分代這一策略。本文介紹了分代策略的目標(biāo),如何分代,以及垃圾回收的觸發(fā)因素。

            文章總結(jié)了JVM垃圾回收策略為什么要分代,如何分代,以及垃圾回收的觸發(fā)因素。

            為什么要分代

            分代的垃圾回收策略,是基于這樣一個(gè)事實(shí):不同的對(duì)象的生命周期是不一樣的。因此,不同生命周期的對(duì)象可以采取不同的收集方式,以便提高回收效率。

            在Java程序運(yùn)行的過程中,會(huì)產(chǎn)生大量的對(duì)象,其中有些對(duì)象是與業(yè)務(wù)信息相關(guān),比如Http請(qǐng)求中的Session對(duì)象、線程、Socket連接,這類對(duì)象跟業(yè)務(wù)直接掛鉤,因此生命周期比較長(zhǎng)。但是還有一些對(duì)象,主要是程序運(yùn)行過程中生成的臨時(shí)變量,這些對(duì)象生命周期會(huì)比較短,比如:String對(duì)象,由于其不變類的特性,系統(tǒng)會(huì)產(chǎn)生大量的這些對(duì)象,有些對(duì)象甚至只用一次即可回收。

            試想,在不進(jìn)行對(duì)象存活時(shí)間區(qū)分的情況下,每次垃圾回收都是對(duì)整個(gè)堆空間進(jìn)行回收,花費(fèi)時(shí)間相對(duì)會(huì)長(zhǎng),同時(shí),因?yàn)槊看位厥斩夹枰闅v所有存活對(duì)象,但實(shí)際上,對(duì)于生命周期長(zhǎng)的對(duì)象而言,這種遍歷是沒有效果的,因?yàn)榭赡苓M(jìn)行了很多次遍歷,但是他們依舊存在。因此,分代垃圾回收采用分治的思想,進(jìn)行代的劃分,把不同生命周期的對(duì)象放在不同代上,不同代上采用最適合它的垃圾回收方式進(jìn)行回收。

            如何分代

            如圖所示:

            如何分代

            虛擬機(jī)中的共劃分為三個(gè)代:年輕代(Young Generation)、年老點(diǎn)(Old Generation)和持久代(Permanent Generation)。其中持久代主要存放的是Java類的類信息,與垃圾收集要收集的Java對(duì)象關(guān)系不大。年輕代和年老代的劃分是對(duì)垃圾收集影響比較大的。

            年輕代:

            所有新生成的對(duì)象首先都是放在年輕代的。年輕代的目標(biāo)就是盡可能快速的收集掉那些生命周期短的對(duì)象。年輕代分三個(gè)區(qū)。一個(gè)Eden區(qū),兩個(gè)Survivor區(qū)(一般而言)。大部分對(duì)象在Eden區(qū)中生成。當(dāng)Eden區(qū)滿時(shí),還存活的對(duì)象將被復(fù)制到Survivor區(qū)(兩個(gè)中的一個(gè)),當(dāng)這個(gè)Survivor區(qū)滿時(shí),此區(qū)的存活對(duì)象將被復(fù)制到另外一個(gè)Survivor區(qū),當(dāng)這個(gè)Survivor去也滿了的時(shí)候,從第一個(gè)Survivor區(qū)復(fù)制過來的并且此時(shí)還存活的對(duì)象,將被復(fù)制“年老區(qū)(Tenured)”。需要注意,Survivor的兩個(gè)區(qū)是對(duì)稱的,沒先后關(guān)系,所以同一個(gè)區(qū)中可能同時(shí)存在從Eden復(fù)制過來 對(duì)象,和從前一個(gè)Survivor復(fù)制過來的對(duì)象,而復(fù)制到年老區(qū)的只有從第一個(gè)Survivor去過來的對(duì)象。而且,Survivor區(qū)總有一個(gè)是空的。同時(shí),根據(jù)程序需要,Survivor區(qū)是可以配置為多個(gè)的(多于兩個(gè)),這樣可以增加對(duì)象在年輕代中的存在時(shí)間,減少被放到年老代的可能。

           年老代:

            在年輕代中經(jīng)歷了N次垃圾回收后仍然存活的對(duì)象,就會(huì)被放到年老代中。因此,可以認(rèn)為年老代中存放的都是一些生命周期較長(zhǎng)的對(duì)象。

            持久代:

            用于存放靜態(tài)文件,如今Java類、方法等。持久代對(duì)垃圾回收沒有顯著影響,但是有些應(yīng)用可能動(dòng)態(tài)生成或者調(diào)用一些class,例如Hibernate等,在這種時(shí)候需要設(shè)置一個(gè)比較大的持久代空間來存放這些運(yùn)行過程中新增的類。持久代大小通過-XX:MaxPermSize=<N>進(jìn)行設(shè)置。

            什么情況下觸發(fā)垃圾回收

            由于對(duì)象進(jìn)行了分代處理,因此垃圾回收區(qū)域、時(shí)間也不一樣。GC有兩種類型:Scavenge GC和Full GC。

            Scavenge GC

            一般情況下,當(dāng)新對(duì)象生成,并且在Eden申請(qǐng)空間失敗時(shí),就會(huì)觸發(fā)Scavenge GC,對(duì)Eden區(qū)域進(jìn)行GC,清除非存活對(duì)象,并且把尚且存活的對(duì)象移動(dòng)到Survivor區(qū)。然后整理Survivor的兩個(gè)區(qū)。這種方式的GC是對(duì)年輕代的Eden區(qū)進(jìn)行,不會(huì)影響到年老代。因?yàn)榇蟛糠謱?duì)象都是從Eden區(qū)開始的,同時(shí)Eden區(qū)不會(huì)分配的很大,所以Eden區(qū)的GC會(huì)頻繁進(jìn)行。因而,一般在這里需要使用速度快、效率高的算法,使Eden去能盡快空閑出來。

            對(duì)整個(gè)堆進(jìn)行整理,包括Young、Tenured和Perm。Full GC因?yàn)樾枰獙?duì)整個(gè)對(duì)進(jìn)行回收,所以比Scavenge GC要慢,因此應(yīng)該盡可能減少Full GC的次數(shù)。在對(duì)JVM調(diào)優(yōu)的過程中,很大一部分工作就是對(duì)于FullGC的調(diào)節(jié)。有如下原因可能導(dǎo)致Full GC:

            ◆ 年老代(Tenured)被寫滿

            ◆ 持久代(Perm)被寫滿

            ◆ System.gc()被顯示調(diào)用

            ◆ 上一次GC之后Heap的各域分配策略動(dòng)態(tài)變化


          posted on 2011-12-14 15:24 順其自然EVO 閱讀(197) 評(píng)論(0)  編輯  收藏


          只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


          網(wǎng)站導(dǎo)航:
           
          <2011年12月>
          27282930123
          45678910
          11121314151617
          18192021222324
          25262728293031
          1234567

          導(dǎo)航

          統(tǒng)計(jì)

          常用鏈接

          留言簿(55)

          隨筆分類

          隨筆檔案

          文章分類

          文章檔案

          搜索

          最新評(píng)論

          閱讀排行榜

          評(píng)論排行榜

          主站蜘蛛池模板: 凤冈县| 大同县| 罗江县| 女性| 韶关市| 庆云县| 蒙山县| 枝江市| 吉林市| 永宁县| 乌鲁木齐市| 客服| 车险| 和龙市| 高邑县| 中卫市| 高阳县| 陆川县| 瑞丽市| 阿巴嘎旗| 罗平县| 曲松县| 宜兴市| 溧阳市| 政和县| 新干县| 永丰县| 都昌县| 双辽市| 巨鹿县| 北辰区| 高邮市| 青河县| 富源县| 普宁市| 朝阳县| 富川| 余江县| 西和县| 江西省| 石阡县|