溫馨提示×

溫馨提示×

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

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

深入淺析Java 中的可視化垃圾回收機制

發(fā)布時間:2020-11-20 15:41:41 來源:億速云 閱讀:192 作者:Leah 欄目:編程語言

這期內(nèi)容當中小編將會給大家?guī)碛嘘P(guān)深入淺析Java 中的可視化垃圾回收機制,文章內(nèi)容豐富且以專業(yè)的角度為大家分析和敘述,閱讀完這篇文章希望大家可以有所收獲。

基礎(chǔ)

當談到釋放不再使用的內(nèi)存,垃圾回收已經(jīng)在很大程度上取代了早期技術(shù),比如手動內(nèi)存管理和引用計數(shù)。

這是件好事,因為內(nèi)存管理令人厭煩,學究式地簿記是計算機擅長的,而不是人擅長的。在這方面,語言的運行時環(huán)境比人強。

現(xiàn)代的垃圾回收非常高效,遠遠超過早期語言中典型的手工分配。通常,具有其它語言背景的人只盯著垃圾回收造成的中斷,卻沒有完全理解自動內(nèi)存管理發(fā)生作用的上下文環(huán)境。

標記&清除是Java(及其它運行時環(huán)境)用于垃圾回收的基本算法。

在標記&清除算法中,引用會從每個線程棧的楨指向程序的堆。所以,從棧開始,循著指針找到所有可能的引用,然后再循著這些引用遞歸下去。

當遞歸完成,就找到了所有的活對象,其它的都是垃圾。

請注意,人們經(jīng)常漏掉的一點是,運行時環(huán)境本身也有一個“分配清單(allocation list)”,上面列出了指向每個對象的指針,該列表由垃圾回收器負責維護,并幫助垃圾回收器進行垃圾清理。因此,運行時環(huán)境總是可以找出由它創(chuàng)建但尚未回收的對象。

深入淺析Java 中的可視化垃圾回收機制

圖一

上面插圖中所示的棧只是一個與單個應(yīng)用程序線程相關(guān)的棧;每個應(yīng)用程序線程都有一個類似的棧,每個棧本身都有一組指向堆的指針。

如果垃圾回收器試圖在應(yīng)用程序運行過程中獲取活對象的快照,那么它就要追蹤運動著的目標,那樣很容易漏掉一些嚴重超時的對象分配,因而無法獲得一個準確的快照。因此,“Stop the World”是有必要的;也就是,停止應(yīng)用程序線程足夠長的時間,以便捕獲活對象的快照。

下面是垃圾回收器必須遵循的兩條黃金法則:

垃圾回收器必須回收所有的垃圾。 垃圾回收器必須從不回收任何活對象。

但這兩條規(guī)則并不是對等的;如果違反了第二條規(guī)則,結(jié)果會使數(shù)據(jù)遭到破壞。

另一方面,如果違反了第一條規(guī)則,則會是另一種情況,系統(tǒng)并不總是能夠回收所有的垃圾,但最終會回收所有的垃圾,那么這是可以接受的,而實際上,這是垃圾回收器的基本原理。

HotSpot

現(xiàn)在,我們來說下HotSpot,它實際上是一個C、C++以及許多特定于平臺的匯編程序組成的混合體。

當人們想到解釋器,就會想到一個很大的while循環(huán),其中包含一個很長的switch語句。但HotSpot解釋器比那個要復雜的多(由于性能原因)。在開始閱讀JDK源代碼的時候,就會發(fā)現(xiàn)HotSpot中實在是有許多匯編程序代碼。

對象創(chuàng)建

Java會預(yù)先分配大量的連續(xù)空間,就是我們所說的“堆”。之后,HotSpot完全在用戶空間里管理這塊內(nèi)存。

如果一個Java進程占用了大量的系統(tǒng)(或內(nèi)核)時間,那么毫無疑問,它不是在進行垃圾回收——因為所有的垃圾回收內(nèi)存“簿記(bookkeeping)”都是在用戶空間進行的。

內(nèi)存池

深入淺析Java 中的可視化垃圾回收機制

圖二

“永久代(PermGen)”是一個存儲區(qū)域,用于保存那些需要在程序生存期內(nèi)一直存活的東西,如類的元數(shù)據(jù)。不過,隨著應(yīng)用程序服務(wù)器的出現(xiàn),它們有自己的類加載器,并且需要重新加載類的元數(shù)據(jù),永久代作為一個優(yōu)化決策開始顯得糟糕,所幸,它在Java 8中消失了。

Java 8將會使用一個名為“元空間(Metaspace)”的新概念。元空間與永久代并不完全相同。它在堆的外面,由操作系統(tǒng)管理。這意味著,它不會在Java堆中,而是在本地內(nèi)存里。目前,這還不是一個非常好的消息,因為沒有多少工具能夠讓用戶輕松地查看本地內(nèi)存。所以,永久代消失是件好事,但工具趕上這個變化還需要一些時間。

Java堆布局

現(xiàn)在,我們來看下Java堆。注意堆空間之間的虛擬空間。它們提供了一點浮動量,以允許對內(nèi)存池進行一定量的尺寸調(diào)整,又不用為任何對象移動付出代價。

深入淺析Java 中的可視化垃圾回收機制

圖三

“弱代假設(shè)(Weak Generational Hypothesis)”

就現(xiàn)狀而言,究竟為什么要將堆分成所有這些內(nèi)存池?

深入淺析Java 中的可視化垃圾回收機制

圖四

有的運行時事實無法通過靜態(tài)分析推導出來。上面的插圖說明有兩組對象:一組存活時間短,一組存活時間長——所以,做額外的簿記以便利用這一事實是有意義的。在Java平臺中,有許多類似的作為優(yōu)化寫入平臺的事實。

演示

Ben Evans進行了一系列的動畫演示。第一個演示是個Flash,說明了對象在Eden區(qū)和一個新生代Survivor空間之間移動,并最終進入老年代的過程。

圖五是用JavaFX再現(xiàn)了同樣的過程。

深入淺析Java 中的可視化垃圾回收機制

圖五

運行時開關(guān)

‘強制性'參數(shù)

-verbose:gc——為用戶輸出一些GC信息 -Xloggc:<文件路徑>——指定日志輸出路徑,要確保磁盤有空間 -XX:+PringGCDetails——為輔助工具提供“最低限度信息(Minimum information)”

——用這個參數(shù)代替-verbose:gc

--XX:PrintTenuringDistribution——“過早提升(Premature promotion)”信息 基本堆大小參數(shù)-Xms<size>—— 設(shè)置預(yù)留給堆的最小內(nèi)存值 -Xmx<size>—— 設(shè)置預(yù)留給堆的最大內(nèi)存值 -XX:MaxPermSize=<size>——設(shè)置永久代的最大內(nèi)存值

——有利于Spring應(yīng)用程序和應(yīng)用服務(wù)器

以前,我們被教導要把-Xms和-Xmx的值設(shè)的一樣大。不過這已經(jīng)變了。因此,現(xiàn)在可以為-Xms設(shè)置一個合理范圍內(nèi)較小的值,或者根本就不設(shè)置,因為堆的適應(yīng)能力現(xiàn)在已經(jīng)非常好了。

其它參數(shù)-XX:NewRatio=N -XX:NewSize=N -XX:MaxNewSize=N -XX:MaxHeapFreeRatio -XX:MinHeapFreeRatio -XX:SurvivorRatio=N -XX:MaxTenuringThreshold=N

深入淺析Java 中的可視化垃圾回收機制

圖六

為什么要有日志文件

日志文件的好處是能夠用于取證分析,可以使用戶免于為了再現(xiàn)問題而不得不再執(zhí)行一次代碼(如果是一個罕見的生產(chǎn)環(huán)境錯誤,那么重現(xiàn)并不容易)。

另外,它們包含的信息比針對內(nèi)存的JMX MXBeans所能提供的信息更多,且不說輪詢JMX本身會引入一系列GC問題。

工具

HP JMeter(用Google查詢一下)

——免費,非??煽?,但不再提供支持/功能增強

GCViewer

——免費,開源,但界面有點丑

GarbageCat

——名字最好聽

IBM GCMV

——支持J9

jClarity Censum

——界面最美觀,而且最有用——不過,這是我們的偏見!

上述就是小編為大家分享的深入淺析Java 中的可視化垃圾回收機制了,如果剛好有類似的疑惑,不妨參照上述分析進行理解。如果想知道更多相關(guān)知識,歡迎關(guān)注億速云行業(yè)資訊頻道。

向AI問一下細節(jié)

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

AI