本篇文章就帶給大家java學習之Jvm垃圾回收器(基礎篇)介紹。有一定的參考價值,有需要的朋友可以參考一下,希望對你們有幫助。
一:概述
在這篇文章中《Jvm運行時資料區》介紹了Java記憶體運行時區域的各個部分,其中程式計數器、虛擬機棧、本地方法棧, 3個區域隨著線程的生存而生存的。記憶體分配和回收都是確定的。隨著線程的結束內存自然就被回收了,因此不需要考慮垃圾回收的問題。而Java堆和方法區則不一樣,各執行緒共享,記憶體的分配和回收都是動態的。因此垃圾收集器所關注的都是這部分記憶體。
接下來我們就討論Jvm是怎麼回收這部分記憶體的。在進行回收前垃圾收集器第一件事就是確定哪些物件還存活,哪些已經死去。下面介紹兩種基礎的回收演算法。
1.1 引用計數演算法
為物件新增一個引用計數器,每當有一個地方引用它時計數器就 1,當引用失效時計數器就-1,。只要計數器等於0的物件就是不可能再使用的。
此演算法在大部分情況下都是一個不錯的選擇,也有一些著名的應用案例。但是Java虛擬機器中是沒有使用的。
優點:實作簡單、判斷效率高。
缺點:很難解決物件之間循環引用的問題。例如下面這個例子
Object a = new Object(); Object b = new Object(); a=b; b=a; a=b=null; //这样就导致gc无法回收他们。
1.2 可達性分析演算法
透過一系列的稱為「GC Roots」的物件作為起始點,從這些節點開始向下搜索,搜尋所走過的路徑稱為引用鏈,當一個物件到GC Roots沒有使用任何引用鏈時,則表示該物件是不可用的。
主流的商用程式語言(Java、C#等)在主流的實作中,都是透過可達性分析來判定物件是否存活的。
透過下圖來清晰的感受gc root與物件所展示的連結。所示灰色區域物件是存活的,Object5/6/7皆是可回收的物件
在Java語言中,可作為GC Roots 的物件包含下列幾種
虛擬機器堆疊(堆疊框架中的本機變數表)中引用的物件
方法區中靜態變數所引用的物件
方法區中常數引用的物件
本機方法堆疊(即一般說的Native 方法)中JNI引用的物件
優點:更精確、嚴謹,可以分析出循環資料結構互相引用的情況;
缺點:實作比較複雜、需要分析大量數據,消耗大量時間、分析過程需要GC停頓(引用關係不能改變),即停頓所有Java執行緒(稱為"Stop The World",是垃圾回收重點關注的問題)。
二:引用
在jdk1.2之後,Java對引用的概念進行了擴充,總體分為4類:強引用、軟引用、弱引用、虛引用,這4中引用強度依序逐漸減弱。
強引用:指在程式碼中普遍存在的,類似Object obj = new Object(); 這類的引用,只有強引用還存在,GC就永遠不會收集被引用的物件。
軟引用:指一些還有用但不是必須的物件。 直到記憶體空間不夠時(拋出OutOfMemoryError之前),才會被垃圾回收。 採用SoftReference類別來實作軟引用
#弱引用:用來描述非必須物件。 當垃圾收集器工作時就會回收掉此類物件。採用WeakReference類別來實作弱引用。
虛擬引用:一個物件是否有虛引用的存在, #完全不會對其生存時間構成影響, 唯一目的就是能在這個物件被回收時收到一個系統通知, 採用PhantomRenference類別實現
2.1 判斷一個對象生存還是死亡
宣告一個物件死亡,至少要經歷兩次標記。
1、第一次標記
如果物件進行可達性分析演算法之後沒發現與GC Roots相連的引用鏈,那它將會第一次標記並且進行一次篩選。
篩選條件:判斷此物件是否有必要執行finalize()方法。
篩選結果:當物件沒有覆寫finalize()方法、或finalize()方法已經被JVM執行過,則判定為可回收物件。如果物件有必要執行finalize()方法,則被放入F-Queue佇列中。稍後在JVM自動建立、低優先權的Finalizer執行緒(可能多個執行緒)中觸發這個方法;
2、第二次標記
GC對F-Queue佇列中的對象進行二次標記。
如果物件在finalize()方法中重新與參考鏈上的任何一個物件建立了關聯,那麼二次標記時則會將它移出「即將回收」集合。如果此時對象還沒成功逃脫,那麼只能被回收了。
3、finalize() 方法
finalize()是Object類別的一個方法、一個物件的finalize()方法只會被系統自動呼叫一次,經過finalize()方法逃脫死亡的對象,第二次不會再呼叫;
特別說明:並不提倡在程式中呼叫finalize()來進行自救。建議忘掉Java程式中該方法的存在。 因為它執行的時間不確定,甚至是否被執行也不確定(Java程式的不正常退出),而且運行代價高昂,無法保證各個物件的呼叫順序(甚至有不同執行緒中呼叫)。
三:回收方法區
永久代的垃圾收集主要分為兩部分內容:廢棄常數和無用的類別。
3.1 回收廢棄常數
回收廢棄常數與Java堆的回收類似。下面舉個栗子說明
假如一個字串「abc」 已經進入常數池中,但目前系統沒有一個string物件是叫做abc的,也就是說,沒有任何string物件的引用指向常數池中的abc常數,也沒用其他地方引用這個字面量。如果這是發生記憶體回收,那麼這個常數abc將會被清理出常數池。常量池中的其他類別(介面)、方法、欄位的符號引用也與此類似。
3.2 回收無用的類別
需要同時滿足下面3個條件的才能算是無用的類別。
該類別所有的實例都已經被回收,也就是Java堆中無任何改類別的實例。
載入該類別的ClassLoader已經被回收。
該類別對應的java.lang.Class物件沒有在任何地方被引用,無法在任何地方透過反射存取該類別的方法
#虛擬機器可以對同時滿足這三個條件的類別進行回收,但不是必須進行回收的。是否對類別進行回收,HotSpot虛擬機器提供了-Xnoclassgc參數進行控制。
總結:以上就是這篇文章的全部內容,希望能對大家的學習有所幫助。更多相關教學請造訪Java影片教學,java開發圖文教學,bootstrap影片教學!
以上是java學習之Jvm垃圾回收器(基礎篇)的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本文討論了使用Maven和Gradle進行Java項目管理,構建自動化和依賴性解決方案,以比較其方法和優化策略。

本文使用Maven和Gradle之類的工具討論了具有適當的版本控制和依賴關係管理的自定義Java庫(JAR文件)的創建和使用。

本文討論了使用咖啡因和Guava緩存在Java中實施多層緩存以提高應用程序性能。它涵蓋設置,集成和績效優勢,以及配置和驅逐政策管理最佳PRA

本文討論了使用JPA進行對象相關映射,並具有高級功能,例如緩存和懶惰加載。它涵蓋了設置,實體映射和優化性能的最佳實踐,同時突出潛在的陷阱。[159個字符]

Java的類上載涉及使用帶有引導,擴展程序和應用程序類負載器的分層系統加載,鏈接和初始化類。父代授權模型確保首先加載核心類別,從而影響自定義類LOA


熱AI工具

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

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

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

SublimeText3 英文版
推薦:為Win版本,支援程式碼提示!

mPDF
mPDF是一個PHP庫,可以從UTF-8編碼的HTML產生PDF檔案。原作者Ian Back編寫mPDF以從他的網站上「即時」輸出PDF文件,並處理不同的語言。與原始腳本如HTML2FPDF相比,它的速度較慢,並且在使用Unicode字體時產生的檔案較大,但支援CSS樣式等,並進行了大量增強。支援幾乎所有語言,包括RTL(阿拉伯語和希伯來語)和CJK(中日韓)。支援嵌套的區塊級元素(如P、DIV),

MinGW - Minimalist GNU for Windows
這個專案正在遷移到osdn.net/projects/mingw的過程中,你可以繼續在那裡關注我們。 MinGW:GNU編譯器集合(GCC)的本機Windows移植版本,可自由分發的導入函式庫和用於建置本機Windows應用程式的頭檔;包括對MSVC執行時間的擴展,以支援C99功能。 MinGW的所有軟體都可以在64位元Windows平台上運作。

SublimeText3漢化版
中文版,非常好用

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