首頁 Java java教程 JVM記憶體管理------GC演算法精解(五分鐘教你終極演算法---分代蒐集演算法)

JVM記憶體管理------GC演算法精解(五分鐘教你終極演算法---分代蒐集演算法)

Dec 28, 2016 pm 03:48 PM
JVM内存管理

引言

何為終極演算法?
其實就是現在的JVM所採用的演算法,並非真正的終極。說不定若干年以後,還會有新的終極演算法,而且幾乎是一定會有,因為LZ相信高人的能力。
那麼分代蒐集演算法是怎麼處理GC的呢?

物件分類

上一章已經說過,分代蒐集演算法是針對物件的不同特性,而使用適合的演算法,這裡面並沒有實際上的新演算法產生。與其說分代蒐集演算法是第四個演算法,不如說它是前三個演算法的實際應用。
首先我們來探討一下物件的不同特性,接下來LZ和各位來一起為這些物件選擇GC演算法。
記憶體中的物件依生命週期的長短大致可以分為三種,以下命名均為LZ個人的命名。
1、夭折對象:朝生夕滅的對象,通俗點講就是活不了多久就得死的對象。
例子:某一個方法的局域變數、循環內的臨時變數等等。
2、老不死對象:這類對像一般活的比較久,歲數很大還不死,但歸根究底,老不死對像也幾乎早晚要死的,但也只是幾乎而已。
範例:快取物件、資料庫連線物件、單例物件(單例模式)等等。
3、不滅對象:這類對像一般一旦出生就幾乎不死了,它們幾乎會一直永生不滅,記得,只是幾乎不滅而已。
例子:String池中的物件(享元模式)、載入過的類別資訊等等。

物件對應的記憶體區域

還記得前面介紹記憶體管理時,JVM對記憶體的分割嗎?
我們將上面三種物件對應到記憶體區域當中,就是夭折物件和老不死物件都在JAVA堆,而不滅物件在方法區。
之前的一章中我們就已經說過,對於JAVA堆,JVM規範要求必須實現GC,因而對於夭折對象和老不死對象來說,死幾乎是必然的結局,但也只是幾乎,還是難免會有有些物件會一直存活到應用程式結束。然而JVM規範對方法區的GC不做要求,所以假設一個JVM實作沒有對方法區實作GC,那麼不滅物件就是真的不滅對象了。
由於不滅對象的生命週期過長,因此分代蒐集演算法就是針對的JAVA堆而設計的,也就是針對夭折對象和老不死對象。

JAVA堆的物件回收(夭折物件和老不死物件)

有了以上分析,我們來看看分代蒐集演算法如何處理JAVA堆的記憶體回收的,也就是夭折物件與老不死物件的回收。
夭折物件:這類物件朝生夕滅,存活時間短,還記得複製演算法的使用要求嗎?那就是物件存活率不能太高,因此夭折物件是最適合使用複製演算法的。
小問:50%記憶體的浪費怎麼辦?
答疑:因為夭折物件一般存活率較低,因此可以不使用50%的內存作為空閒,一般的,使用兩塊10%的內存作為空閒和活動區間,而另外80%的內存,則是用來給新建物件分配記憶體的。一旦發生GC,將10%的活動區間與另外80%中存活的物件轉移到10%的空閒區間,接下來,將先前90%的記憶體全部釋放,以此類推。
為了讓各位更清楚的看出來這個GC流程,LZ給出下面圖示。

JVM記憶體管理------GC演算法精解(五分鐘教你終極演算法---分代蒐集演算法)


圖中標註了三個區域中在各個階段,各自記憶體的情況。相信看著圖,它的GC流程已經不難理解了。
不過有兩點LZ需要提一下,第一點是使用這樣的方式,我們只浪費了10%的內存,這個是可以接受的,因為我們換來了內存的整齊排列與GC速度。第二點是,這個策略的前提是,每次存活的物件佔用的記憶體不能超過這10%的大小,一旦超過,多出的物件就無法複製。
為了解決上面的意外情況,也就是存活對象佔用的內存太大時的情況,高手們將JAVA堆分成兩部分來處理,上述三個區域則是第一部分,稱為新生代或者年輕代。而餘下的一部分,專門存放老不死對象的則稱為年老代。
是不是很貼切的名字呢?下面我們來看看老不死對象的處理方式。
老不死對象:這一類物件存活率非常高,因為它們大多是從新生代轉過來的。就像人一樣,活的年月久了,就變成老不死了。
通常情況下,以下兩種情況發生的時候,物件會從新生代區域轉到年老帶區域。
1、在新生代裡的每一個對象,都會有一個年齡,當這些對象的年齡到達一定程度時(年齡就是熬過的GC次數,每次GC如果對象存活下來,則年齡加1),則會被轉到年老代,而這個轉入年老代的年齡值,一般在JVM中是可以設定的。
2、在新生代存活物件佔用的記憶體超過10%時,則多餘的物件會放入年老代。這種時候,年老代就是新生代的「備用倉庫」。
針對老不死對象的特性,顯然不再適合使用複製演算法,因為它的存活率太高,而且不要忘了,如果年老代再使用複製演算法,它可是沒有備用倉庫的。因此一般針對老不死物件只能採用標記/整理或標記/清除演算法。

方法區的對象回收(不滅對象)

以上兩種情況已經解決了GC的大部分問題,因為JAVA堆是GC的主要關注對象,而以上也已經包含了分代蒐集演算法的全部內容,接下來對於不滅對象的回收,已經不屬於分代蒐集演算法的內容。
不滅對象存在於方法區,在我們常用的hotspot虛擬機(JDK預設的JVM)中,方法區也被親切的稱為永久代,又是一個很貼切的名字不是嗎?
其實在很久很久以前,是不存在永久代的。當時永久代與年老代都存放在一起,裡麵包含了JAVA類別的實例資訊以及類別資訊。但後來發現,對於類資訊的卸載幾乎很少發生,因此便將二者分開。幸運的是,這樣做確實提高了不少性能。於是永久代便就被拆分出來了。
這一部分區域的GC與年老代採用相似的方法,由於都沒有“備用倉庫”,二者都是只能使用標記/清除和標記/整理演算法。

回收的時機

JVM在進行GC時,並非每次都對上面三個記憶體區域一起回收的,大部分時候回收的都是指新生代。因此GC依照回收的區域又分了兩種類型,一種是普通GC(minor GC),一種是全域GC(major GC or Full GC),它們所針對的區域如下。
普通GC(minor GC):只針對新生代區域的GC。
全局GC(major GC or Full GC):針對年老代的GC,偶爾伴隨對新生代的GC以及對永久代的GC。
由於年老代與永久代相對來說GC效果不好,而且二者的內存使用增長速度也慢,因此一般情況下,需要經過好幾次普通GC,才會觸發一次全局GC。

結束語

以上就是JVM記憶體管理------GC演算法精解(五分鐘教你終極演算法---分代蒐集演算法)的內容,更多相關內容請關注PHP中文網( www.php.cn)!


本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

<🎜>:泡泡膠模擬器無窮大 - 如何獲取和使用皇家鑰匙
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
北端:融合系統,解釋
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
Mandragora:巫婆樹的耳語 - 如何解鎖抓鉤
3 週前 By 尊渡假赌尊渡假赌尊渡假赌

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

熱門話題

Java教學
1665
14
CakePHP 教程
1424
52
Laravel 教程
1321
25
PHP教程
1269
29
C# 教程
1249
24
公司安全軟件導致應用無法運行?如何排查和解決? 公司安全軟件導致應用無法運行?如何排查和解決? Apr 19, 2025 pm 04:51 PM

公司安全軟件導致部分應用無法正常運行的排查與解決方法許多公司為了保障內部網絡安全,會部署安全軟件。 ...

如何將姓名轉換為數字以實現排序並保持群組中的一致性? 如何將姓名轉換為數字以實現排序並保持群組中的一致性? Apr 19, 2025 pm 11:30 PM

將姓名轉換為數字以實現排序的解決方案在許多應用場景中,用戶可能需要在群組中進行排序,尤其是在一個用...

如何使用MapStruct簡化系統對接中的字段映射問題? 如何使用MapStruct簡化系統對接中的字段映射問題? Apr 19, 2025 pm 06:21 PM

系統對接中的字段映射處理在進行系統對接時,常常會遇到一個棘手的問題:如何將A系統的接口字段有效地映�...

IntelliJ IDEA是如何在不輸出日誌的情況下識別Spring Boot項目的端口號的? IntelliJ IDEA是如何在不輸出日誌的情況下識別Spring Boot項目的端口號的? Apr 19, 2025 pm 11:45 PM

在使用IntelliJIDEAUltimate版本啟動Spring...

如何優雅地獲取實體類變量名構建數據庫查詢條件? 如何優雅地獲取實體類變量名構建數據庫查詢條件? Apr 19, 2025 pm 11:42 PM

在使用MyBatis-Plus或其他ORM框架進行數據庫操作時,經常需要根據實體類的屬性名構造查詢條件。如果每次都手動...

Java對像如何安全地轉換為數組? Java對像如何安全地轉換為數組? Apr 19, 2025 pm 11:33 PM

Java對象與數組的轉換:深入探討強制類型轉換的風險與正確方法很多Java初學者會遇到將一個對象轉換成數組的�...

電商平台SKU和SPU數據庫設計:如何兼顧用戶自定義屬性和無屬性商品? 電商平台SKU和SPU數據庫設計:如何兼顧用戶自定義屬性和無屬性商品? Apr 19, 2025 pm 11:27 PM

電商平台SKU和SPU表設計詳解本文將探討電商平台中SKU和SPU的數據庫設計問題,特別是如何處理用戶自定義銷售屬...

如何利用Redis緩存方案高效實現產品排行榜列表的需求? 如何利用Redis緩存方案高效實現產品排行榜列表的需求? Apr 19, 2025 pm 11:36 PM

Redis緩存方案如何實現產品排行榜列表的需求?在開發過程中,我們常常需要處理排行榜的需求,例如展示一個�...

See all articles