欧美亚洲中文,在线国自产视频,欧洲一区在线观看视频,亚洲综合中文字幕在线观看

      1. <dfn id="rfwes"></dfn>
          <object id="rfwes"></object>
        1. 站長資訊網
          最全最豐富的資訊網站

          jvm的垃圾回收機制是什么

          jvm的垃圾回收機制是GC(Garbage Collection),也叫垃圾收集器。GC基本原理:將內存中不再被使用的對象進行回收;GC中用于回收的方法稱為收集器,由于GC需要消耗一些資源和時間,Java在對對象的生命周期特征進行分析后,按照新生代、老年代的方式來對對象進行收集,以盡可能的縮短GC對應用造成的暫停。

          jvm的垃圾回收機制是什么

          本教程操作環(huán)境:windows7系統(tǒng)、java8版、DELL G3電腦。

          什么是垃圾回收

          java相較于c、c++語言的優(yōu)勢之一是自帶垃圾回收器,垃圾回收是指不定時去堆內存中清理不可達對象。不可達的對象并不會馬上就會直接回收, 垃圾收集器在一個Java程序中的執(zhí)行是自動的,不能強制執(zhí)行,程序員唯一能做的就是通過調用System.gc 方法來建議執(zhí)行垃圾收集器,但其是否可以執(zhí)行,什么時候執(zhí)行卻都是不可知的。這也是垃圾收集器的最主要的缺點。當然相對于它給程序員帶來的巨大方便性而言,這個缺點是瑕不掩瑜的。

          為什么需要垃圾回收

          如果不進行垃圾回收,內存遲早都會被消耗空,因為我們在不斷的分配內存空間而不進行回收。除非內存無限大,我們可以任性的分配而不回收,但是事實并非如此。所以,垃圾回收是必須的。

          jvm垃圾回收原理

          在JVM運行時數(shù)據區(qū)存在一個堆區(qū), 堆是一個巨大的對象池。在這個對象池中管理著數(shù)量巨大的對象實例,而池中對象的引用層次,有的是很深的。一個被頻繁調用的接口,每秒生成對象的速度,是很大的,同時,對象之間的關系,形成了一張巨大的網。

          Java 一直在營造一種無限內存的氛圍,但對象不能只增不減,所以需要垃圾回收;那 JVM 是如何判斷哪些對象應該被回收?哪些應該被保持呢?這就要用到JVM的垃圾回收機制了,也就是我們常說的GC(Garbage Collection),也叫垃圾收集器。

          GC (Garbage Collection:即垃圾回收)的基本原理:將內存中不再被使用的對象進行回收,GC中用于回收的方法稱為收集器,由于GC需要消耗一些資源和時間,Java在對對象的生命周期特征進行分析后,按照新生代、老年代的方式來對對象進行收集,以盡可能的縮短GC對應用造成的暫停

          ● 對新生代的對象的收集稱為minor GC
          ● 對老年代的對象的收集稱為Full GC
          ● 程序中主動調用System.gc()強制執(zhí)行的GC為Full GC

          不同的對象引用類型, GC會采用不同的方法進行回收,JVM對象的引用分為了四種類型:
          ● 強引用:默認情況下,對象采用的均為強引用(這個對象的實例沒有其他對象引用,GC時才會被回收)
          ● 軟引用:軟引用是Java中提供的一種比較適合于緩存場景的應用(只有在內存不夠用的情況下才會被GC)
          ● 弱引用:在GC時一定會被GC回收
          ● 虛引用:由于虛引用只是用來得知對象是否被GC

          對象被標記為垃圾方法

          JVM的內存結構包括五大區(qū)域:程序計數(shù)器、虛擬機棧、本地方法棧堆區(qū)、方法區(qū)。其中程序計數(shù)器、虛擬機棧、本地方法棧3個區(qū)域隨線程而生、隨線程而滅,因此這幾個區(qū)域的內存分配和回收都具備確定性,就不需要過多考慮回收的問題,因為方法結束或者線程結束時,內存自然就跟隨著回收了。而Java堆區(qū)和方法區(qū)則不一樣,這部分內存的分配和回收是動態(tài)的,正是垃圾收集器所需關注的部分。

          1. 引用計數(shù)器

          引用計數(shù)是垃圾收集器中的早期策略。在這種方法中,堆中每個對象實例都有一個引用計數(shù)。當一個對象被創(chuàng)建時,就將該對象實例分配給一個變量,該變量計數(shù)設置為1。當任何其它變量被賦值為這個對象的引用時,計數(shù)加1(a = b,則b引用的對象實例的計數(shù)器+1),但當一個對象實例的某個引用超過了生命周期或者被設置為一個新值時,對象實例的引用計數(shù)器減1。任何引用計數(shù)器為0的對象實例可以被當作垃圾收集。當一個對象實例被垃圾收集時,它引用的任何對象實例的引用計數(shù)器減1。

          優(yōu)點: 引用計數(shù)收集器可以很快的執(zhí)行,交織在程序運行中。對程序需要不被長時間打斷的實時環(huán)境比較有利。
          缺點: 無法檢測出循環(huán)引用。如父對象有一個對子對象的引用,子對象反過來引用父對象。這樣,他們的引用計數(shù)永遠不可能為0。

          jvm的垃圾回收機制是什么

          對以上代碼通過引用計數(shù)法分析:

          jvm的垃圾回收機制是什么

          jvm的垃圾回收機制是什么

          jvm的垃圾回收機制是什么

          2. 可達性分析

          可達性算法是目前主流的虛擬機都采用的算法,程序把所有的引用關系看作一張圖,從一個節(jié)點GC Roots開始,尋找對應的引用節(jié)點,找到這個節(jié)點以后,繼續(xù)尋找這個節(jié)點的引用節(jié)點,當所有的引用節(jié)點尋找完畢之后,剩余的節(jié)點則被認為是沒有被引用到的節(jié)點,即無用的節(jié)點,無用的節(jié)點將會被判定為是可回收的對象。

          在Java語言中,可作為GC Roots的對象包括下面幾種:
          ● 虛擬機棧中引用的對象(棧幀中的本地變量表);
          ● 方法區(qū)中類靜態(tài)屬性引用的對象;
          ● 方法區(qū)中常量引用的對象;
          ● 本地方法棧中JNI(Native方法)引用的對象。

          jvm的垃圾回收機制是什么

          可以得出對象實例1、2、4、6都具有對象可達性,也就是存活對象,不能被GC回收的對象。而隨想實例3、5雖然直接相連,但并沒有任何一個GC Roots與之相連,即GC Roots不可達對象,就會被GC回收的對象。

          三、垃圾回收算法

          1. 標記-清除算法

          標記/清除算法的基本思想就跟它的名字一樣,分為“標記”和“清除”兩個階段:首先標記出所有需要回收的對象,在標記完成后統(tǒng)一回收所有被標記的對象。
          標記階段:
          標記的過程其實就是前面介紹的可達性分析算法的過程,遍歷所有的 GC Roots 對象,對從 GCRoots 對象可達的對象都打上一個標識,一般是在對象的 header 中,將其記錄為可達對象。
          清除階段:
          清除的過程是對堆內存進行遍歷,如果發(fā)現(xiàn)某個對象沒有被標記為可達對象(通過讀取對象header 信息),則將其回收。

          jvm的垃圾回收機制是什么

          上圖是標記/清除算法的示意圖,在標記階段,從對象 GC Root 1 可以訪問到 B 對象,從 B 對象又可以訪問到 E 對象,因此從 GC Root 1 到 B、E 都是可達的,同理,對象 F、G、J、K 都是可達對象;到了清除階段,所有不可達對象都會被回收。
          在垃圾收集器進行 GC 時,必須停止所有 Java 執(zhí)行線程(也稱"Stop The World"),原因是在標記階段進行可達性分析時,不可以出現(xiàn)分析過程中對象引用關系還在不斷變化的情況,否則的話可達性分析結果的準確性就無法得到保證。在等待標記清除結束后,應用線程才會恢復運行。

          標記/清除算法缺點:
          效率問題
          標記和清除兩個階段的效率都不高,因為這兩個階段都需要遍歷內存中的對象,很多時候內存中的對象實例數(shù)量是非常龐大的,這無疑很耗費時間,而且 GC 時需要停止應用程序,這會導致非常差的用戶體驗。
          空間問題
          標記清除之后會產生大量不連續(xù)的內存碎片(從上圖可以看出),內存空間碎片太多可能會導致以后在程序運行過程中需要分配較大對象時,無法找到足夠的連續(xù)內存而不得不提前觸發(fā)另一次垃圾回收動作。

          2. 復制算法

          復制算法是將可用內存按容量劃分為大小相等的兩塊,每次使用其中的一塊。當這一塊的內存用完了,就將還存活的對象復制到另一塊內存上,然后把這一塊內存所有的對象一次性清理掉
          jvm的垃圾回收機制是什么

          復制算法每次都是對整個半區(qū)進行內存回收,這樣就減少了標記對象遍歷的時間,在清除使用區(qū)域對象時,不用進行遍歷,直接清空整個區(qū)域內存,而且在將存活對象復制到保留區(qū)域時也是按地址順序存儲的,這樣就解決了內存碎片的問題,在分配對象內存時不用考慮內存碎片等復雜問題,只需要按順序分配內存即可。

          復制算法缺點:
          復制算法簡單高效,優(yōu)化了標記清除算法的效率低、內存碎片多問題,存在缺點:
          ● 將內存縮小為原來的一半,浪費了一半的內存空間,代價太高;
          ● 如果對象的存活率很高,極端一點的情況假設對象存活率為 100%,那么我們需要將所有存活的對象復制一遍,耗費的時間代價也是不可忽視的。

          3. 標記-整理算法

          標記-整理算法算法與標記/清除算法很像,事實上,標記/整理算法的標記過程任然與標記/清除算法一樣,但后續(xù)步驟不是直接對可回收對象進行回收,而是讓所有存活的對象都向一端移動,然后直接清理掉端邊線以外的內存。
          jvm的垃圾回收機制是什么

          可以看到,回收后可回收對象被清理掉了,存活的對象按規(guī)則排列存放在內存中。這樣一來,當我們給新對象分配內存時,jvm 只需要持有內存的起始地址即可。標記/整理算法彌補了標記/清除算法存在內存碎片的問題消除了復制算法內存減半的高額代價,可謂一舉兩得。

          標記/整理缺點:
          ● 效率不高:不僅要標記存活對象,還要整理所有存活對象的引用地址,在效率上不如復制算法。

          4. 分代回收算法

          分代收集算法的思想是按對象的存活周期不同將內存劃分為幾塊一般是把 Java 堆分為新生代和老年代(還有一個永久代,是 HotSpot 特有的實現(xiàn),其他的虛擬機實現(xiàn)沒有這一概念,永久代的收集效果很差,一般很少對永久代進行垃圾回收),這樣就可以根據各個年代的特點采用最合適的收集算法。

          特點:
          新生代:朝生夕滅,存活時間很短。采用復制算法來收集
          老年代:經過多次 Minor GC 而存活下來,存活周期長。采用標記/清除算法或者標記/整理算法收集老年代

          新生代中每次垃圾回收都發(fā)現(xiàn)有大量的對象死去,只有少量存活,因此采用復制算法回收新生代,只需要付出少量對象的復制成本就可以完成收集;
          老年代中對象的存活率高,不適合采用復制算法,而且如果老年代采用復制算法,它是沒有額外的空間進行分配擔保的,因此必須使用標記/清理算法或者標記/整理算法來進行回收。

          jvm的垃圾回收機制是什么

          新生代中的對象“朝生夕死”,每次GC時都會有大量對象死去,少量存活,使用復制算法。新生代又分為Eden區(qū)和Survivor區(qū)(Survivor from、Survivor to),大小比例默認為8:1:1。
          老年代中的對象因為對象存活率高、沒有額外空間進行分配擔保,就使用標記-清除或標記-整理算法。
          新產生的對象優(yōu)先進去Eden區(qū),當Eden區(qū)滿了之后再使用Survivor from,當Survivor from 也滿了之后就進行Minor GC(新生代GC),將Eden和Survivor from中存活的對象copy進入Survivor to,然后清空Eden和Survivor from,這個時候原來的Survivor from成了新的Survivor to,原來的Survivor to成了新的Survivor from。復制的時候,如果Survivor to 無法容納全部存活的對象,則根據老年代的分配擔保(類似于銀行的貸款擔保)將對象copy進去老年代,如果老年代也無法容納,則進行Full GC(老年代GC)。
          大對象直接進入老年代:JVM中有個參數(shù)配置
          -XX:PretenureSizeThreshold,令大于這個設置值的對象直接進入老年代,目的是為了避免在Eden和Survivor區(qū)之間發(fā)生大量的內存復制。
          長期存活的對象進入老年代:JVM給每個對象定義一個對象年齡計數(shù)器,如果對象在Eden出生并經過第一次Minor GC后仍然存活,并且能被Survivor容納,將被移入Survivor并且年齡設定為1。沒熬過一次Minor GC,年齡就加1,當他的年齡到一定程度(默認為15歲,可以通過XX:MaxTenuringThreshold來設定),就會移入老年代。但是JVM并不是永遠要求年齡必須達到最大年齡才會晉升老年代,如果Survivor 空間中相同年齡(如年齡為x)所有對象大小的總和大于Survivor的一半,年齡大于等于x的所有對象直接進入老年代,無需等到最大年齡要求。

          分代回收:

          我們從一個object1來說明其在分代垃圾回收算法中的回收軌跡。

          1、object1新建,出生于新生代的Eden區(qū)域。
          jvm的垃圾回收機制是什么
          2、minor GC,object1 還存活,移動到From suvivor空間,此時還在新生代。

          jvm的垃圾回收機制是什么

          3、minor GC,object1 仍然存活,此時會通過復制算法,將object1移動到ToSuv區(qū)域,此時object1的年齡age+1。
          jvm的垃圾回收機制是什么
          4、minor GC,object1 仍然存活,此時survivor中和object1同齡的對象并沒有達到survivor的一半,所以此時通過復制算法,將fromSuv和Tosuv 區(qū)域進行互換,存活的對象被移動到了Tosuv。
          jvm的垃圾回收機制是什么
          5、minor GC,object1 仍然存活,此時survivor中和object1同齡的對象已經達到survivor的一半以上(toSuv的區(qū)域已經滿了),object1被移動到了老年代區(qū)域。
          jvm的垃圾回收機制是什么
          6、object1存活一段時間后,發(fā)現(xiàn)此時object1不可達GcRoots,而且此時老年代空間比率已經超過了閾值,觸發(fā)了majorGC(也可以認為是fullGC,但具體需要垃圾收集器來聯(lián)系),此時object1被回收了。fullGC會觸發(fā) stop the world。
          jvm的垃圾回收機制是什么
          在以上的新生代中,我們有提到對象的age,對象存活于survivor狀態(tài)下,不會立即晉升為老年代對象,以避免給老年代造成過大的影響,它們必須要滿足以下條件才可以晉升:
          1、minor gc 之后,存活于survivor 區(qū)域的對象的age會+1,當超過(默認)15的時候,轉移到老年代。
          2、動態(tài)對象,如果survivor空間中相同年齡所有的對象大小的綜合和大于survivor空間的一半,年級大于或等于該年紀的對象就可以直接進入老年代。

          贊(0)
          分享到: 更多 (0)
          網站地圖   滬ICP備18035694號-2    滬公網安備31011702889846號