Ⅰ java中的垃圾回收是什麼意思
Java中的垃圾回收是指Java虛擬機提供的一種能力,用於在空閑時間以不定時的方式動態回收無任何引用的對象占據的內存空間。具體來說:
回收對象:垃圾回收的目標是回收無任何引用的對象占據的內存空間,而不是對象本身。這些對象被認為是「垃圾」,因為它們已經不被程序中的任何部分所使用。
運行時間:垃圾回收器的運行時間是不確定的,由JVM決定。它在運行時是間歇執行的,這意味著它會在JVM認為合適的時候進行垃圾回收,而不是按照固定的時間間隔。
強制回收:雖然可以通過系統命令來強制JVM進行垃圾回收,但是這個命令下達後並不能保證JVM會立即響應執行。然而,經驗表明,在下達命令後,JVM通常會在短期內執行垃圾回收操作。
內存管理:系統通常會在感到內存緊缺時去執行垃圾回收操作,以釋放不再使用的內存空間。垃圾回收的頻率對程序性能有影響:過於頻繁會導致性能下降,因為垃圾回收過程會佔用CPU資源;而過於稀疏則可能導致內存緊缺,影響程序的正常運行。
因此,Java中的垃圾回收是一種重要的內存管理機制,它有助於自動管理內存,減少內存泄漏的風險,但也需要開發者注意其可能帶來的性能影響。
Ⅱ java垃圾回收器有哪幾種
Java垃圾回收演算法和收集器是系統自動管理內存的關鍵部分。主要有以下幾種:
1. 標記-清除演算法:簡單實現,不產生內存碎片,但清除操作可能引起停頓且導致大量不連續內存碎片。
2. 復制演算法:實現簡單,無內存碎片,適用於新生代,但需要額外內存空間。
3. 標記-壓縮演算法:解決內存碎片問題,移動存活對象,減少停頓時間,但操作復雜。
4. 分代收集演算法:依據對象生命周期,將堆劃分為新生代和老年代,針對性管理,提高效率,增加系統復雜度。
5. 增量收集與並發收集:為其他演算法優化,提升收集效率。
Java中常見的收集器包括:
1. Serial Collector:單線程收集,適用於單CPU或小內存場景。
2. Parallel Collector:多線程執行,適用於多CPU且不敏感於停頓時間的應用。
3. ParNew Collector:專為多線程環境設計,配合CMS收集器使用,提升多代垃圾收集效率。
4. CMS Collector:以最短停頓時間為目標,實現並發標記、清理,大部分工作與用戶線程並發進行。
5. G1 Collector:分代收集器,將堆劃分為多個區域,預測停頓時間,採用標記-壓縮演算法,兼顧吞吐量和停頓時間。
6. ZGC與Shenandoah:低延遲垃圾收集器,實現亞毫秒級停頓,採用顏色指針、讀屏障、並發壓縮等技術。
這些演算法和收集器各有特點,開發者應根據應用需求選擇合適的垃圾回收配置,以實現最佳性能。
Ⅲ JAVA垃圾回收器-上篇
學習背景
在學習垃圾回收器之前,我們首先明確目標。大多數人學習垃圾回收器主要是為了應對面試,因為這一知識點十分重要,系統全面的介紹卻不多見。本篇主要講述垃圾回收器的實現思想與部分原理,為方便閱讀,我們還會介紹一些術語。
垃圾回收器是什麼
垃圾回收器作為JVM的一部分,負責管理內存,包括對象的分配與回收,以確保程序運行安全且高效。雖然從職責上來說,它可以視為一個抽象實體,但實際上,不同JVM實現中可能存在多種垃圾回收器,甚至一個JVM內部就可能包含多個回收器。它們依據對象特點選擇演算法與內存管理方式,有效利用內存資源。
在開始深入學習之前,讓我們了解一下JVM的幾個主要實現及其歷史,這些實現正是垃圾回收器的理論基礎。
在後續的理論講解中,我們將重點使用HotSpot虛擬機作為示例進行討論。
JVM內存區域
在探索垃圾回收器之前,理解JVM內存布局至關重要,這有助於我們更好地理解回收機制及其工作原理。《Java虛擬機規范》定義了JVM內存布局,主要包括幾個關鍵區域。
接下來的解釋可能會讓你感到困惑,但請放心,我們即將步入正題。在深入垃圾回收器理論之前,我們也將簡要介紹對象創建與內存布局的內容,但為了保持文章流暢,這部分將在後續編譯器內容中詳細介紹。
垃圾回收理論指導思想
在了解垃圾回收器的工作機制之前,先思考如何回收一個對象。大致而言,這分為識別垃圾與引用計數與可達性分析演算法兩個步驟。
識別垃圾
假設我們有一個記錄對象引用次數的區域,每當其他對象引用某個對象時,次數加一,引用失效時減一。當引用次數歸零,說明對象已無用,可以被回收。這是簡單樸素的思路,許多軟體採用此法,如FlashPlayer、Python、Redis等,但在Java中,主流JVM未採用此演算法,因為它難以處理循環引用問題。
可達性分析演算法
主流現代JVM採用可達性分析演算法,從稱為GC根的對象出發,遍歷其引用的對象,找到引用鏈上的存活對象,以此判斷對象是否可以被回收。
何為引用
在上述介紹中,我們遇到了一個關鍵概念——引用。引用定義了對象之間的關系,其正式定義在JDK 1.2後出現。引用大致分為四類,但在本文中,我們主要關注其基本用法。
回收垃圾分代收集演算法
在介紹內存回收方式之前,我們先了解分代收集演算法。通過將對象按年齡分代,年輕對象存於新生代,年長對象存於老年代。這影響了垃圾回收演算法的實現。
標記清除演算法
標記清除演算法通過標記與清除階段回收內存。標記階段與可達性分析一致,清除階段統一回收標記的對象。但這種方法可能導致內存碎片,影響後續分配。
復制演算法
復制演算法改進了標記清除演算法,將內存劃分為兩部分,每次使用其中一部分。回收後,存活對象復制到另一部分,清理原區域。此方法避免了內存不連續問題,但犧牲了運行內存空間。
現代商業虛擬機採用這種演算法,如HotSpot中,新生代劃分為Eden區與兩塊Survivor區。回收時,將存活對象復制到Survivor區,清理Eden與原Survivor區。默認比例為8:1:1,每次新生代可用內存為整個新生代的90%。
標記整理演算法
復制演算法存在不足,因此老年代通常採用標記整理演算法。此演算法首先標記存活對象,將它們移動至內存一端,然後回收邊界外內存。
HotSpot的垃圾回收設計
HotSpot虛擬機的垃圾收集設計基於前述理論,下面我們將介紹實際設計點,這些點需要結合具體垃圾回收器進行深入理解。
根節點枚舉
可達性分析演算法中,找到GC根對象至關重要。HotSpot使用OopMap加速此過程,記錄對象與棧、寄存器中的引用位置,避免掃描方法區。
安全點與安全區
生成Oop Map的位置限於安全點與安全區。安全點確保程序長時間執行,安全區允許引用關系在一定代碼內保持不變。
垃圾回收器介紹
理論鋪墊後,我們將開始實際垃圾回收器的學習。
Serial搜集器
這是JDK最古老的收集器,單線程運行,暫停所有工作線程。在Client模式下,它作為新生代默認收集器。
Serial Old收集器
它是Serial收集器的老年代版本,同樣為單線程收集器,採用標記整理演算法。在Client模式下使用,配合Parallel Scavenge使用時作為CMS失敗時的後備方案。
ParNew收集器
Serial收集器的多線程版本,Server模式下新生代首選。單核環境下性能與Serial相當。
Parallel Scavenge收集器
多線程新生代收集器,追求可控吞吐量,更關注運行時間與垃圾收集時間的比值。有重要參數可調整吞吐量與停頓時間。
Parallel Old收集器
Parallel Old是ParNew的老年代版本,使用多線程與標記整理演算法。配合Parallel Scavenge使用,適合吞吐量優先場景。
CMS(Concurrent Mark Sweep)收集器
CMS是老年代收集器,基於標記清除演算法,目標是降低停頓時間。開啟方法為-XX:+UseConcMarkSweepGC,回收過程包含初始標記、並發標記、重新標記與並發清除等步驟。
CMS收集器優點與缺點
CMS收集器減少STW時間,適合網路伺服器,但也存在停頓時間長、內存碎片、並發控制復雜等缺點。
總結與展望
本文主要回顧了垃圾回收器的基礎理論與常見實現。了解了這些理論後,下一步是深入學習具體垃圾回收器的回收細節。在後續文章中,我們將詳細介紹G1與ZGC等收集器,以及GC日誌的知識。敬請期待。