91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Java垃圾回收機制的底層原理是什么

發布時間:2021-08-03 11:27:54 來源:億速云 閱讀:111 作者:Leah 欄目:大數據

這篇文章給大家介紹Java垃圾回收機制的底層原理是什么,內容非常詳細,感興趣的小伙伴們可以參考借鑒,希望對大家能有所幫助。

3.1.2 垃圾回收機制

Java 內存運行時區域中的程序計數器、虛擬機棧、本地方法棧隨線程而生滅,棧中的棧幀隨著方法的進入和退出而有條不紊地執行著出棧和入棧操作。每一個棧幀中分配多少內存基本上是在類結構確定下來時就已知的(盡管在運行期會由 JIT 編譯器進行一些優化),因此這幾個區域的內存分配和回收都具備確定性,不需要過多考慮回收的問題,因為方法結束或者線程結束時,內存自然就跟隨著回收了。

而 Java 堆不一樣,一個接口中的多個實現類需要的內存可能不一樣,一個方法中的多個分支需要的內存也可能不一樣,我們只有在程序處于運行期間時才能知道會創建哪些對象,這部分內存的分配和回收都是動態的,垃圾收集器所關注的是這部分內存。

自動垃圾收集

自動垃圾收集是查看堆內存,識別正在使用那些對象,那些對象未被刪除,刪除未被使用對象的過程。使用中對象或引用的對象意味著程序的某些部分任然維護指向該對象的指針。程序的任何部分都不再引用未使用的對象或未引用的對象,則可以回收未引用對象的內存。在C語言中,內存的分配和釋放是手動的過程,在Java語言中內存的分配和回收是由垃圾收集器自動處理的。

而在自動垃圾收集中如何確定那些內存需要被回收,通常來說第一步就是標記,利用引用計數,可達性分析等來標記那些內存正在使用,那些內存不在使用。

引用計數法

引用計數法主要是通過給對象中添加一個引用計數器,每當一個地方引用它時,計數器的值就加1,當引用失效時,計數器的值就減1,當計數器的值為0時,對象就是不可能被使用的,可以對其進行垃圾回收。引用計數法的實現簡單,效率也比較高,但是它很難解決對象之間循環引用的問題。

可達性分析算法

可達性分析算法,也稱為根搜索算法,這個算法的基本思路就是通過一系列的名為“GC Roots”的對象為起始點,從這些節點開始向下搜索,搜索所走過的路徑稱為引用鏈,當一個對象到“GC Roots”沒有任何引用鏈相連,則證明對象是不可用的,可以對其進行垃圾回收。

簡單來說,將對象及其引用關系看作一個圖,選定活動的對象作為“GC Roots”,然后跟蹤引用鏈條,如果一個對象和”GC Roots“之間不可達,也就是不存在引用,即可認為是可回收對象。

引用類型和可達性級別

引用類型

  • 強引用(Strong Reference):最常見的普通引用,只要還有強引用指向一個對象,就不會回收

  • 軟引用(Soft Reference):JVM認為內存不足阿時候,才會去試圖回收軟引用指向的對象(緩存場景)

  • 弱引用(Weak Reference):雖然是引用,但隨時有可能被回收掉

  • 虛引用(Phantom Reference):不能通過它訪問對象,提供對象被finalize以后,執行指定邏輯的機制。

可達性級別

  • 強可達(Strongly Reachable):一個對象可以有一個或多個線程可以不通過各種引用訪問到的情況

  • 軟可達(Softly Reachable):只能通過軟引用才能訪問到的狀態

  • 弱引用(Weakly Reachable):只能通過弱引用訪問時的狀態,當弱引用被清除的時候,就符合銷毀條件

  • 幻像可達(Phantom Reachable):不存在其他引用,并且finalize過了,只有幻像引用指向這個對象

  • 不可達(Unreachable):意味著對象可以被清除了

垃圾收集算法

目前主流廣泛使用的垃圾收集算法,主要有標記-清除算法(Mark-Sweep),復制算法(Coping)以及標記-整理算法(Mark-Compact)。

標記-清除算法:首先識別出所有要回收的對象,然后進行清除。標記,清除的過程效率有限,存在內存碎片化的問題,不適合特別大的堆。其他收集算法基本都是基于標記-清除的思路進行改進。

復制算法:劃分兩塊同等大小的區域,收集時將活著的對象復制到另一塊區域。復制過程中將對象順序放置,就可以避免內存碎片化。但是復制加上預留內存有一定的浪費

標記-整理算法:類似于標記-清除,但為避免內存碎片化,它會在清理過程中將對象移動,以確保移動后的對象占用連續的內存

分代收集

根據對象的存活周期,將內存劃分為幾個區域,不同區域采用合適的垃圾收集算法。目前主流的JVM一般將堆內存分為新生代和老年代(大小比列為1:2),而新生代又被分為了eden、from survivor、to survivor(大小比列為8:1:1)。在新生代中,每次垃圾收集時都發現有大量對象死去,只有少量存活,那么就可以選用復制算法,只需付出少量對象的復制成本就可以完成收集。在老年代中,對象存活率高,就可以使用標記-清除,標記-整理算法。

新生代幾乎是所有JAVA對象出生的地方,JAVA對象申請的內存和存放都是在這個地方,JVM每次只會使用新生代中的eden和其中一塊survivor來為對象服務,所以無論什么時候,都會有一塊survivor空間空閑。當對象經過一次minor gc后仍然存活,并且能夠被另外一塊survivor所容納,則使用復制算法將這些仍然存活的對象復制到另外一塊survior區域中,然后清理掉eden和之前使用的survivor區域,并將這些存活的對象年齡+1,以后對象在survivor中每熬過一次minor gc則年齡增加1,當年齡達到某個值時(默認15,通過設置參數-XX:MaxTenuringThreshold來設置),這些對象就會進入老年代。當然,對于一些較大的對象可以直接進入老年代,可以根據-XX:+PretenureSizeThreshold設置大對象進入老年代的閾值。

垃圾收集器

垃圾收集算法只是內存回收的理論方法,垃圾收集器才是內存回收的具體實現。Java虛擬機規范中對垃圾收集器的實現沒有具體的規定,不同廠商,不同版本的垃圾收集器可能會差別很大。目前常見的垃圾收集器主要有Serial收集器,ParNew收集器,Parallel Scavenge收集器,Serial Old收集器,Parallel Old收集器,CMS收集器,G1收集器。這些垃圾收集器各有優劣,一般都是組合在一起使用,下圖展示了在新生代和老年代可用的垃圾收集器組合:

Serial收集器

Serial收集器是一個串行收集器,使用單個線程來執行所有垃圾收集工作,適合單處理器機器,GC在工作的時候將暫停其他所有的工作線程,即”Stop The World“。Serial收集器是一個新生代的單線程收集器,它使用復制算法,是虛擬機在client模式下的默認新生代收集器,可以通過設置參數-XX:+UseSerialGC來使用。

ParNew收集器

ParNew收集器可以理解為串行收集器的多線程版本,其整體算法和Serial比較相似,除了使用多線程進行垃圾回收,其他的基本和Serial收集器一樣。ParNew收集器是虛擬機在server模式下的默認新生代收集器,可以通過設置參數-XX:+UseParNewGC來使用。默認情況下它開啟的線程數和CPU數量相同,也可以通過設置參數-XX:ParallelGCThreads來配置垃圾收集的線程數。

Parallel Scavenge收集器

Parallel Scavenge收集器也是一個新生代的并行垃圾收集器,使用的也是復制算法。Parallel Scavenge收集器的目標是達到一個可控制的吞吐量。吞吐量就是CPU運行用戶代碼的時間與CPU消耗的總時間的比值,即吞吐量=運行用戶代碼時間/(運行用戶代碼時間+垃圾收集時間)。Parallel Scavenge收集器提供-XX:MaxGCPauseMillis來控制最大垃圾收集停頓時間和-XX:GCTimeRatio來直接設置吞吐量的大小。

Serial Old收集器

Serial Old收集器是Serial收集器的在老年代使用的版本,它采用了標記-整理算法,可以通過設置參數-XX:+UseSerialOldGC來使用。

Parallel Old收集器

Parallel Old收集器是Parallel Scavenge收集器的老年代版本,使用多線程和標記-整理算法,可以通過設置參數-XX:+UseParallelOldGC來使用。

CMS收集器

CMS收集器是一個并發收集器,CMS即Concurrent Mark Swap,主要用于老年代,使用標記-清除算法,可以通過設置參數-XX:+UseConcMarkSweepGC來使用。CMS收集器可以并行的執行用戶程序和垃圾回收,這樣就可以減少回收的停頓時間。CMS收集器設計的主要目的就是為了減少回收停頓時間,目前很多的Java應用都集中在互聯網網站或B/S系統服務端,這類應用尤其重視服務的響應速度,希望系統停頓時間最短,CMS收集器非常符合這類應用的要求。當然,CMS收集器也有自己的缺點,它會占用更多的CPU資源,并和用戶線程爭搶,同時由于采用標記-清除算法,存在著內存碎片化的問題,長時間運行等情況下可能發full gc導致惡劣的停頓。

CMS收集器垃圾收集的整個過程有4個步驟,初始標記,并發標記,重寫標記以及并發清除。其中初始標記和重寫標記任然需要”Stop The World”,但是速度很快,整個過程中耗時的操作在并發標記和并發清除階段,在這個過程中,收集器線程都可以和用戶線程一起工作。

G1收集器

G1(Garage First)收集器是當前垃圾收集器技術最前沿的成果,在JDK7中開始使用(可以通過配置-XX:+UseG1GC使用),從JDK9開始G1已經成為JVM默認的垃圾收集器。G1垃圾收集器也是以關注延遲為目標、服務器端應用的垃圾收集器,其目標就是取代CMS垃圾收集器。

G1采用了分區(Region)的思路,將整個堆空間分成若干個大小相等的內存區域,每次分配對象空間將逐段地使用內存,這樣最大的好處就是化整為零,避免全內存掃描,只需要按照區域來進行掃描即可。啟動時可以通過參數-XX:G1HeapRegionSize=n可指定分區大小(1MB~32MB,且必須是2的冪),默認將整堆劃分為2048個分區。在堆的使用上,整個內存分區不存在物理上的年輕代和老年代的區別,也不需要完全獨立的 Survivor to space 堆做復制準備。G1 只有邏輯上的分代概念,或者說每個分區都可能隨 G1 的運行在不同代之間前后切換。

G1收集器整體采用標記-整理算法,局部是通過是通過復制算法,不會產生內存碎片,能充分利用多 CPU、多核環境硬件優勢,盡量縮短”Stop The World”的時間

下圖左側為G1收集器的內存劃分概圖,紅色為新生代(沒有S的為eden區域,有S的為survivor區域),藍色為老年代(帶有H的表示humongous ,存放humongous objects,即大于等于region一半的對象)。右側為G1收集器的垃圾收集環圖,G1的垃圾收集在層次上可以分為兩個階段,young-only階段和Space-reclamation階段,在young-only階段又分為Initial Mark ,Remark,Cleanup。

關于Java垃圾回收機制的底層原理是什么就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

剑川县| 浠水县| 凭祥市| 阳西县| 独山县| 呼伦贝尔市| 宣化县| 上虞市| 博兴县| 门源| 安庆市| 从江县| 辽阳市| 鸡东县| 沅陵县| 德保县| 武平县| 合作市| 类乌齐县| 任丘市| 双流县| 余姚市| 搜索| 六盘水市| 庄河市| 台东县| 通河县| 增城市| 秭归县| 彰化市| 南阳市| 会泽县| 苏尼特右旗| 邻水| 勐海县| 舒兰市| 怀集县| 昭觉县| 射洪县| 正安县| 湘潭县|