首頁 Java java教程 Java記憶體機制與GC回收機制的解析(圖文介紹)

Java記憶體機制與GC回收機制的解析(圖文介紹)

Feb 27, 2019 am 11:21 AM
java

這篇文章帶給大家的內容是關於Java記憶體機制和GC回收機制的解析(圖文介紹),有一定的參考價值,有需要的朋友可以參考一下,希望對你有幫助。

Java程式碼執行與編譯的過程

Java記憶體機制與GC回收機制的解析(圖文介紹)

#Java記憶體管理

java記憶體模型分割

Java記憶體機制與GC回收機制的解析(圖文介紹)

物件的存取定位

Object obj = new Object();
登入後複製

Java記憶體機制與GC回收機制的解析(圖文介紹)

java物件創建及初始化

java物件創建之後,就會在堆記憶體擁有自己的一塊區域,接著就是物件的初始化過程。類別成員初始化順序總結:先靜態後普通再建構, 先父類後子類,同級看書寫順序

  1. 先執行父類靜態變數與靜態程式碼區塊,再執行子類別靜態變數與靜態程式碼區塊

  2. 先執行父類別普通變數與程式碼區塊,再執行父類別建構器(static方法)

  3. 先執行子類別普通變數與程式碼區塊,再執行子類別建構器(static方法)

  4. #static方法初始化先於普通方法,靜態初始化只有在必要時刻才進行並且只初始化一次。

注意:子類別的建構方法,不管這個建構方法帶不帶參數,預設的它都會先去尋找父類別的不帶參數的建構方法。如果父類別沒有不帶參數的建構方法,那麼子類別必須用supper關鍵子來呼叫父類別帶參數的建構方法,否則編譯不能通過。

GC回收機制

java中垃圾回收器可以自動回收無用物件佔據的內存,但它只負責釋放java中創建的物件所佔據的所有內存,透過某種創建物件之外的方式為物件分配的記憶體空間則無法被垃圾回收器回收;而且垃圾回收本身也有開銷,GC的優先權比較低,所以如果JVM沒有面臨記憶體耗盡,它是不會去浪費資源進行垃圾回收以恢復記憶體的。最後我們會發現,只要程式沒有瀕臨儲存空間用完那一刻,物件佔用的空間就總也無法釋放。我們可以透過程式碼System.gc()來主動啟動一個垃圾回收器(雖然JVM不會立刻去回收),在釋放new分配記憶體空間之前,將會透過finalize()釋放用其他方法分配的記憶體空間。

哪些記憶體需要回收

java堆、方法區的記憶體

Java記憶體機制與GC回收機制的解析(圖文介紹)

何時回收

  1. 引用計數法

#為物件新增一個引用計數器,每當有一個地方引用它時,計數器加一。反之每當一個引用失效時,計數器減一。當計數器為0時,則表示物件不被引用。舉個例子:
Java記憶體機制與GC回收機制的解析(圖文介紹)
但是,引用計數法無法解決物件之間的循環引用,見下例
Java記憶體機制與GC回收機制的解析(圖文介紹)
  1. 可達性分析

設立若干根物件(GC Root),每個物件都是一個子節點,當一個物件找不到根時,就認為該對像不可達。
Java記憶體機制與GC回收機制的解析(圖文介紹)
沒有一條從根到Object4 和 Object5的路徑,表示這兩個物件到根是不可達的,可以被回收。 java中,可以作為GC Roots的物件包括:java虛擬機器堆疊中引用的物件;方法區中靜態變數所引用的物件;方法區中常數引用的物件;本地方法堆疊中引用的物件。

怎麼回收

  1. 標記-清除演算法

先標記所有需要回收的對象,在標記完成後統一回收所有被標記的對象。
此演算法有兩個問題:1)標記和清除過程效率不高。主要由於垃圾收集器需要從GC Roots根對像中遍歷所有可達的對象,並給這些對象加上一個標記,表明此對像在清除的時候被跳過,然後在清除階段,垃圾收集器會從Java堆中從頭到尾進行遍歷,如果有物件沒有被打上標記,那麼這個物件就會被清除。顯然遍歷的效率是很低的;2)會產生很多不連續的空間碎片,所以可能會導致程序運行過程中需要分配較大的對象的時候,無法找到足夠的內存而不得不提前出發一次垃圾回收。
  1. 複製演算法

將記憶體分成兩塊,每次只使用一塊。當這一塊記憶體滿了,就將還存活的物件複製到另一塊上,並且嚴格按照記憶體位址排列,然後把已使用的那塊記憶體統一回收。
優點是:能夠得到連續的記憶體空間
缺點是:浪費了一半記憶體
現代的JVM並不是依照1:1劃分記憶體空間的,而是將記憶體分成一塊較大的Eden區和兩塊較小的Survivor區,每次使用其中的Eden和一塊Survivor區。回收的時候,將Eden和Survivor中還存活著的物件一次複製到另外一塊Survivor中,最後把Eden和Survivor的空間清理出來。其實這裡還有一個問題:就是如果垃圾回收後,存活的物件需要的空間大於剩餘一塊Survivor的空間怎麼辦?答案是需要依賴其他記憶體進行分配(這裡主要指的是老年代)。
  1. 標記-整理演算法

與標記-清除演算法過程一樣,只不過在標記後不是對未標記的記憶體區域進行清理,二是讓所有的存活物件都往一端移動,然後清理掉邊界外的記憶體
  1. #分代演算法

所謂分代就是根據物件的生命週期把記憶體分成幾塊,這樣就可以根據物件的「年齡」來選擇合適的垃圾回收演算法。在java中,把記憶體中的物件依生命長短分為:1.新生代:生命週期短,例如局部變數;2.老年代:生命週期長的物件;3.永久代:很少會被回收,生命週期長,例如載入的class資訊。
新生代和老年代存放在堆區,永久代存放在方法區。大物件會直接進入老年代,例如很長的字串或很大的數組,大物件對於JVM記憶體分配是個壞消息,因為大物件需要找到連續內存,否則會觸發gc,所以短命的大物件是需要盡量避免的。長期存活的對象進入老年代,對像在新生代每經歷一次minor gc,年齡加1, 默認達到15歲會進入老年代。每次Minor GC時,虛擬機會偵測每次晉升到老年代的平均大小是否大於老年代當前剩餘大小,如果小於,則進行full gc。
新生代使用複製演算法(因為存活的物件較少,而死亡的物件過多,如果使用標記-清除演算法的話,需要遍歷標記,顯然效率較低,而使用複製演算法就可以把存活的較少的物件複製到可用記憶體區域中,這樣效率就較高)進行GC回收,老年代因為存活率高,所以使用標記清除或標記整理演算法回收。

#

以上是Java記憶體機制與GC回收機制的解析(圖文介紹)的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡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脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
1 個月前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳圖形設置
1 個月前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您聽不到任何人,如何修復音頻
1 個月前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.聊天命令以及如何使用它們
1 個月前 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 中的完美數 Java 中的完美數 Aug 30, 2024 pm 04:28 PM

Java 完美數指南。這裡我們討論定義,如何在 Java 中檢查完美數?

Java 中的隨機數產生器 Java 中的隨機數產生器 Aug 30, 2024 pm 04:27 PM

Java 隨機數產生器指南。在這裡,我們透過範例討論 Java 中的函數,並透過範例討論兩個不同的生成器。

Java中的Weka Java中的Weka Aug 30, 2024 pm 04:28 PM

Java 版 Weka 指南。這裡我們透過範例討論簡介、如何使用 weka java、平台類型和優點。

Java 中的史密斯數 Java 中的史密斯數 Aug 30, 2024 pm 04:28 PM

Java 史密斯數指南。這裡我們討論定義,如何在Java中檢查史密斯號?帶有程式碼實現的範例。

Java Spring 面試題 Java Spring 面試題 Aug 30, 2024 pm 04:29 PM

在本文中,我們保留了最常被問到的 Java Spring 面試問題及其詳細答案。這樣你就可以順利通過面試。

突破或從Java 8流返回? 突破或從Java 8流返回? Feb 07, 2025 pm 12:09 PM

Java 8引入了Stream API,提供了一種強大且表達力豐富的處理數據集合的方式。然而,使用Stream時,一個常見問題是:如何從forEach操作中中斷或返回? 傳統循環允許提前中斷或返回,但Stream的forEach方法並不直接支持這種方式。本文將解釋原因,並探討在Stream處理系統中實現提前終止的替代方法。 延伸閱讀: Java Stream API改進 理解Stream forEach forEach方法是一個終端操作,它對Stream中的每個元素執行一個操作。它的設計意圖是處

Java 中的時間戳至今 Java 中的時間戳至今 Aug 30, 2024 pm 04:28 PM

Java 中的時間戳記到日期指南。這裡我們也結合範例討論了介紹以及如何在java中將時間戳記轉換為日期。

Java程序查找膠囊的體積 Java程序查找膠囊的體積 Feb 07, 2025 am 11:37 AM

膠囊是一種三維幾何圖形,由一個圓柱體和兩端各一個半球體組成。膠囊的體積可以通過將圓柱體的體積和兩端半球體的體積相加來計算。本教程將討論如何使用不同的方法在Java中計算給定膠囊的體積。 膠囊體積公式 膠囊體積的公式如下: 膠囊體積 = 圓柱體體積 兩個半球體體積 其中, r: 半球體的半徑。 h: 圓柱體的高度(不包括半球體)。 例子 1 輸入 半徑 = 5 單位 高度 = 10 單位 輸出 體積 = 1570.8 立方單位 解釋 使用公式計算體積: 體積 = π × r2 × h (4

See all articles