乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      JVM內(nèi)存模型以及垃圾收集策略解析 - 信心,恒心,野心,愛(ài)心兼具者,可謂準(zhǔn)成功人士! -...

       citycanyon 2010-03-01

      JVM內(nèi)存模型以及垃圾收集策略解析

      文章分類(lèi):Java編程

      首先祝大家春節(jié)愉快,幾個(gè)月前研究了一下JVM的內(nèi)存模型,整理學(xué)習(xí)心得,共享出來(lái)和大家一起學(xué)習(xí)討論進(jìn)步。

       

      一 JVM內(nèi)存模型

      1.1 Java

      Java棧是與每一個(gè)線(xiàn)程關(guān)聯(lián)的,JVM在創(chuàng)建每一個(gè)線(xiàn)程的時(shí)候,會(huì)分配一定的??臻g給線(xiàn)程。它主要用來(lái)存儲(chǔ)線(xiàn)程執(zhí)行過(guò)程中的局部變量,方法的返回值,以及方法調(diào)用上下文。??臻g隨著線(xiàn)程的終止而釋放。

      StackOverflowError:如果在線(xiàn)程執(zhí)行的過(guò)程中,??臻g不夠用,那么JVM就會(huì)拋出此異常,這種情況一般是死遞歸造成的。

      1.2 

      Java中堆是由所有的線(xiàn)程共享的一塊內(nèi)存區(qū)域,堆用來(lái)保存各種JAVA對(duì)象,比如數(shù)組,線(xiàn)程對(duì)象等。

      1.2.1 Generation

      JVM堆一般又可以分為以下三部分:

      Ø Perm

      Perm代主要保存class,method,filed對(duì)象,這部門(mén)的空間一般不會(huì)溢出,除非一次性加載了很多的類(lèi),不過(guò)在涉及到熱部署的應(yīng)用服務(wù)器的時(shí)候,有時(shí)候會(huì)遇到java.lang.OutOfMemoryError : PermGen space 的錯(cuò)誤,造成這個(gè)錯(cuò)誤的很大原因就有可能是每次都重新部署,但是重新部署后,類(lèi)的class沒(méi)有被卸載掉,這樣就造成了大量的class對(duì)象保存在了perm中,這種情況下,一般重新啟動(dòng)應(yīng)用服務(wù)器可以解決問(wèn)題。

      Ø Tenured

      Tenured區(qū)主要保存生命周期長(zhǎng)的對(duì)象,一般是一些老的對(duì)象,當(dāng)一些對(duì)象在Young復(fù)制轉(zhuǎn)移一定的次數(shù)以后,對(duì)象就會(huì)被轉(zhuǎn)移到Tenured區(qū),一般如果系統(tǒng)中用了application級(jí)別的緩存,緩存中的對(duì)象往往會(huì)被轉(zhuǎn)移到這一區(qū)間。

      Ø Young

      Young區(qū)被劃分為三部分,Eden區(qū)和兩個(gè)大小嚴(yán)格相同的Survivor區(qū),其中Survivor區(qū)間中,某一時(shí)刻只有其中一個(gè)是被使用的,另外一個(gè)留做垃圾收集時(shí)復(fù)制對(duì)象用,在Young區(qū)間變滿(mǎn)的時(shí)候,minor GC就會(huì)將存活的對(duì)象移到空閑的Survivor區(qū)間中,根據(jù)JVM的策略,在經(jīng)過(guò)幾次垃圾收集后,任然存活于Survivor的對(duì)象將被移動(dòng)到Tenured區(qū)間。

      1.2.2 Sizing the Generations

      JVM提供了相應(yīng)的參數(shù)來(lái)對(duì)內(nèi)存大小進(jìn)行配置。

      正如上面描述,JVM中堆被分為了3個(gè)大的區(qū)間,同時(shí)JVM也提供了一些選項(xiàng)對(duì)Young,Tenured的大小進(jìn)行控制。

      Ø Total Heap 

      -Xms :指定了JVM初始啟動(dòng)以后初始化內(nèi)存

      -Xmx:指定JVM堆得最大內(nèi)存,在JVM啟動(dòng)以后,會(huì)分配-Xmx參數(shù)指定大小的內(nèi)存給JVM,但是不一定全部使用,JVM會(huì)根據(jù)-Xms參數(shù)來(lái)調(diào)節(jié)真正用于JVM的內(nèi)存

      -Xmx -Xms之差就是三個(gè)Virtual空間的大小

      Ø Young Generation

      -XX:NewRatio=8意味著tenured 和 young的比值81,這樣eden+2*survivor=1/9

      堆內(nèi)存

      -XX:SurvivorRatio=32意味著eden和一個(gè)survivor的比值是321,這樣一個(gè)Survivor就占Young區(qū)的1/34.

      -Xmn 參數(shù)設(shè)置了年輕代的大小

      Ø Perm Generation

      -XX:PermSize=16M -XX:MaxPermSize=64M

      Thread Stack

      -XX:Xss=128K

       

      1.3 堆棧分離的好處

       

      呵呵,其它的先不說(shuō)了,就來(lái)說(shuō)說(shuō)面向?qū)ο蟮脑O(shè)計(jì)吧,當(dāng)然除了面向?qū)ο蟮脑O(shè)計(jì)帶來(lái)的維護(hù)性,復(fù)用性和擴(kuò)展性方面的好處外,我們看看面向?qū)ο笕绾吻擅畹睦昧硕褩7蛛x。如果從JAVA內(nèi)存模型的角度去理解面向?qū)ο蟮脑O(shè)計(jì),我們就會(huì)發(fā)現(xiàn)對(duì)象它完美的表示了堆和棧,對(duì)象的數(shù)據(jù)放在堆中,而我們編寫(xiě)的那些方法一般都是運(yùn)行在棧中,因此面向?qū)ο蟮脑O(shè)計(jì)是一種非常完美的設(shè)計(jì)方式,它完美的統(tǒng)一了數(shù)據(jù)存儲(chǔ)和運(yùn)行。

       

      二 JAVA垃圾收集器

      2.1 垃圾收集簡(jiǎn)史

      垃圾收集提供了內(nèi)存管理的機(jī)制,使得應(yīng)用程序不需要在關(guān)注內(nèi)存如何釋放,內(nèi)存用完后,垃圾收集會(huì)進(jìn)行收集,這樣就減輕了因?yàn)槿藶榈墓芾韮?nèi)存而造成的錯(cuò)誤,比如在C++語(yǔ)言里,出現(xiàn)內(nèi)存泄露時(shí)很常見(jiàn)的。

      Java語(yǔ)言是目前使用最多的依賴(lài)于垃圾收集器的語(yǔ)言,但是垃圾收集器策略從20世紀(jì)60年代就已經(jīng)流行起來(lái)了,比如Smalltalk,Eiffel等編程語(yǔ)言也集成了垃圾收集器的機(jī)制。

      2.2 常見(jiàn)的垃圾收集策略

      所有的垃圾收集算法都面臨同一個(gè)問(wèn)題,那就是找出應(yīng)用程序不可到達(dá)的內(nèi)存塊,將其釋放,這里面得不可到達(dá)主要是指應(yīng)用程序已經(jīng)沒(méi)有內(nèi)存塊的引用了,而在JAVA中,某個(gè)對(duì)象對(duì)應(yīng)用程序是可到達(dá)的是指:這個(gè)對(duì)象被根(根主要是指類(lèi)的靜態(tài)變量,或者活躍在所有線(xiàn)程棧的對(duì)象的引用)引用或者對(duì)象被另一個(gè)可到達(dá)的對(duì)象引用。

      2.2.1 Reference Counting(引用計(jì)數(shù))

       引用計(jì)數(shù)是最簡(jiǎn)單直接的一種方式,這種方式在每一個(gè)對(duì)象中增加一個(gè)引用的計(jì)數(shù),這個(gè)計(jì)數(shù)代表當(dāng)前程序有多少個(gè)引用引用了此對(duì)象,如果此對(duì)象的引用計(jì)數(shù)變?yōu)?span style="FONT-FAMILY: Times New Roman">0,那么此對(duì)象就可以作為垃圾收集器的目標(biāo)對(duì)象來(lái)收集。

      優(yōu)點(diǎn):

      簡(jiǎn)單,直接,不需要暫停整個(gè)應(yīng)用

      缺點(diǎn):

      1.需要編譯器的配合,編譯器要生成特殊的指令來(lái)進(jìn)行引用計(jì)數(shù)的操作,比如每次將對(duì)象賦值給新的引用,或者者對(duì)象的引用超出了作用域等。

      2.不能處理循環(huán)引用的問(wèn)題

      2.2.2 跟蹤收集器

      跟蹤收集器首先要暫停整個(gè)應(yīng)用程序,然后開(kāi)始從根對(duì)象掃描整個(gè)堆,判斷掃描的對(duì)象是否有對(duì)象引用,這里面有三個(gè)問(wèn)題需要搞清楚:

      1.如果每次掃描整個(gè)堆,那么勢(shì)必讓GC的時(shí)間變長(zhǎng),從而影響了應(yīng)用本身的執(zhí)行。因此在JVM里面采用了分代收集,在新生代收集的時(shí)候minor gc只需要掃描新生代,而不需要掃描老生代。

      2.JVM采用了分代收集以后,minor gc只掃描新生代,但是minor gc怎么判斷是否有老生代的對(duì)象引用了新生代的對(duì)象,JVM采用了卡片標(biāo)記的策略,卡片標(biāo)記將老生代分成了一塊一塊的,劃分以后的每一個(gè)塊就叫做一個(gè)卡片,JVM采用卡表維護(hù)了每一個(gè)塊的狀態(tài),當(dāng)JAVA程序運(yùn)行的時(shí)候,如果發(fā)現(xiàn)老生代對(duì)象引用或者釋放了新生代對(duì)象的引用,那么就JVM就將卡表的狀態(tài)設(shè)置為臟狀態(tài),這樣每次minor gc的時(shí)候就會(huì)只掃描被標(biāo)記為臟狀態(tài)的卡片,而不需要掃描整個(gè)堆。具體如下圖:

      3.GC在收集一個(gè)對(duì)象的時(shí)候會(huì)判斷是否有引用指向?qū)ο?,?/span>JAVA中的引用主要有四種:Strong reference,Soft reference,Weak reference,Phantom reference.

      Ø Strong Reference 

      強(qiáng)引用是JAVA中默認(rèn)采用的一種方式,我們平時(shí)創(chuàng)建的引用都屬于強(qiáng)引用。如果一個(gè)對(duì)象沒(méi)有強(qiáng)引用,那么對(duì)象就會(huì)被回收。

      public void testStrongReference(){

      Object referent = new Object();

      Object strongReference = referent;

      referent = null;

      System.gc();

      assertNotNull(strongReference);

      }

       

          

      Ø Soft Reference

      軟引用的對(duì)象在GC的時(shí)候不會(huì)被回收,只有當(dāng)內(nèi)存不夠用的時(shí)候才會(huì)真正的回收,因此軟引用適合緩存的場(chǎng)合,這樣使得緩存中的對(duì)象可以盡量的再內(nèi)存中待長(zhǎng)久一點(diǎn)。

      Public void testSoftReference(){

      String  str =  "test";

      SoftReference<String> softreference = new SoftReference<String>(str);

      str=null;

      System.gc();

      assertNotNull(softreference.get());

      }

       

      Ø Weak reference

      弱引用有利于對(duì)象更快的被回收,假如一個(gè)對(duì)象沒(méi)有強(qiáng)引用只有弱引用,那么在GC后,這個(gè)對(duì)象肯定會(huì)被回收。

      Public void testWeakReference(){

      String  str =  "test";

      WeakReference<String> weakReference = new WeakReference<String>(str);

      str=null;

      System.gc();

      assertNull(weakReference.get());

      }

       

      Ø Phantom reference 

      2.2.2.1 Mark-Sweep Collector(標(biāo)記-清除收集器)

      標(biāo)記清除收集器最早由Lisp的發(fā)明人于1960年提出,標(biāo)記清除收集器停止所有的工作,從根掃描每個(gè)活躍的對(duì)象,然后標(biāo)記掃描過(guò)的對(duì)象,標(biāo)記完成以后,清除那些沒(méi)有被標(biāo)記的對(duì)象。

      優(yōu)點(diǎn):

      解決循環(huán)引用的問(wèn)題

      不需要編譯器的配合,從而就不執(zhí)行額外的指令

      缺點(diǎn):

      1.每個(gè)活躍的對(duì)象都要進(jìn)行掃描,收集暫停的時(shí)間比較長(zhǎng)。

      2.2.2.2 Copying Collector(復(fù)制收集器)

      復(fù)制收集器將內(nèi)存分為兩塊一樣大小空間,某一個(gè)時(shí)刻,只有一個(gè)空間處于活躍的狀態(tài),當(dāng)活躍的空間滿(mǎn)的時(shí)候,GC就會(huì)將活躍的對(duì)象復(fù)制到未使用的空間中去,原來(lái)不活躍的空間就變?yōu)榱嘶钴S的空間。

      復(fù)制收集器具體過(guò)程可以參考下圖:

      優(yōu)點(diǎn):

      只掃描可以到達(dá)的對(duì)象,不需要掃描所有的對(duì)象,從而減少了應(yīng)用暫停的時(shí)間

      缺點(diǎn):

      1.需要額外的空間消耗,某一個(gè)時(shí)刻,總是有一塊內(nèi)存處于未使用狀態(tài)

      2.復(fù)制對(duì)象需要一定的開(kāi)銷(xiāo)

      2.2.2.3 Mark-Compact Collector(標(biāo)記-整理收集器)

      標(biāo)記整理收集器汲取了標(biāo)記清除和復(fù)制收集器的優(yōu)點(diǎn),它分兩個(gè)階段執(zhí)行,在第一個(gè)階段,首先掃描所有活躍的對(duì)象,并標(biāo)記所有活躍的對(duì)象,第二個(gè)階段首先清除未標(biāo)記的對(duì)象,然后將活躍的的對(duì)象復(fù)制到堆得底部。標(biāo)記整理收集器的過(guò)程示意圖請(qǐng)參考下圖:

       

      Mark-compact策略極大的減少了內(nèi)存碎片,并且不需要像Copy Collector一樣需要兩倍的空間。

      2.3 JVM的垃圾收集策略

         GC的執(zhí)行時(shí)要耗費(fèi)一定的CPU資源和時(shí)間的,因此在JDK1.2以后,JVM引入了分代收集的策略,其中對(duì)新生代采用"Mark-Compact"策略,而對(duì)老生代采用了“Mark-Sweep"的策略。其中新生代的垃圾收集器命名為“minor gc”,老生代的GC命名為"Full Gc 或者Major GC".其中用System.gc()強(qiáng)制執(zhí)行的是Full Gc.

      2.3.1 Serial Collector

      Serial Collector是指任何時(shí)刻都只有一個(gè)線(xiàn)程進(jìn)行垃圾收集,這種策略有一個(gè)名字“stop the whole world",它需要停止整個(gè)應(yīng)用的執(zhí)行。這種類(lèi)型的收集器適合于單CPU的機(jī)器。

      Serial Copying Collector

      此種GC-XX:UseSerialGC選項(xiàng)配置,它只用于新生代對(duì)象的收集。1.5.0以后.

      -XX:MaxTenuringThreshold來(lái)設(shè)置對(duì)象復(fù)制的次數(shù)。當(dāng)eden空間不夠的時(shí)候,GC會(huì)將eden的活躍對(duì)象和一個(gè)名叫From survivor空間中尚不夠資格放入Old代的對(duì)象復(fù)制到另外一個(gè)名字叫To Survivor的空間。而此參數(shù)就是用來(lái)說(shuō)明到底From survivor中的哪些對(duì)象不夠資格,假如這個(gè)參數(shù)設(shè)置為31,那么也就是說(shuō)只有對(duì)象復(fù)制31次以后才算是有資格的對(duì)象。

      這里需要注意幾個(gè)個(gè)問(wèn)題:

      Ø  From SurvivorTo survivor的角色是不斷的變化的,同一時(shí)間只有一塊空間處于使用狀態(tài),這個(gè)空間就叫做From Survivor區(qū),當(dāng)復(fù)制一次后角色就發(fā)生了變化。

      Ø  如果復(fù)制的過(guò)程中發(fā)現(xiàn)To survivor空間已經(jīng)滿(mǎn)了,那么就直接復(fù)制到old generation.

      Ø  比較大的對(duì)象也會(huì)直接復(fù)制到Old generation,在開(kāi)發(fā)中,我們應(yīng)該盡量避免這種情況的發(fā)生。

      Serial  Mark-Compact Collector

      串行的標(biāo)記-整理收集器是JDK5 update6之前默認(rèn)的老生代的垃圾收集器,此收集使得內(nèi)存碎片最少化,但是它需要暫停的時(shí)間比較長(zhǎng)

      2.3.2 Parallel Collector 

      Parallel Collector主要是為了應(yīng)對(duì)多CPU,大數(shù)據(jù)量的環(huán)境。

      Parallel Collector又可以分為以下兩種:

      Parallel Copying Collector

      此種GC-XX:UseParNewGC參數(shù)配置,它主要用于新生代的收集,GC可以配合CMS一起使用。1.4.1以后

      Parallel Mark-Compact Collector

      此種GC-XX:UseParallelOldGC參數(shù)配置,此GC主要用于老生代對(duì)象的收集。1.6.0

      Parallel scavenging Collector

      此種GC-XX:UseParallelGC參數(shù)配置,它是對(duì)新生代對(duì)象的垃圾收集器,但是它不能和CMS配合使用,它適合于比較大新生代的情況,此收集器起始于jdk 1.4.0。它比較適合于對(duì)吞吐量高于暫停時(shí)間的場(chǎng)合。

      Serial gcParallel gc可以用如下的圖來(lái)表示:

      2.3.3 Concurrent Collector

      Concurrent Collector通過(guò)并行的方式進(jìn)行垃圾收集,這樣就減少了垃圾收集器收集一次的時(shí)間,這種GC在實(shí)時(shí)性要求高于吞吐量的時(shí)候比較有用。

      此種GC可以用參數(shù)-XX:UseConcMarkSweepGC配置,此GC主要用于老生代Perm代的收集。

       

      參考資料

      1 http://developers./mobility/midp/articles/garbage/

      2 http://developers./mobility/midp/articles/garbagecollection2/

      3 http://blogs./watt/resource/jvm-options-list.html

      4 http://java./developer/technicalArticles/Programming/turbo/

      5 http://www.ibm.com/developerworks/library/j-jtp10283/index.html?S_TACT=105AGX52&S_CMP=cn-a-j

      6 http://www.ibm.com/developerworks/library/j-jtp11253/index.html?S_TACT=105AGX52&S_CMP=cn-a-j

        本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶(hù)發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評(píng)論

        發(fā)表

        請(qǐng)遵守用戶(hù) 評(píng)論公約

        類(lèi)似文章 更多