53.垃圾回收算法的实现原理、启动Java垃圾回收、Java垃圾回收过程、垃圾回收中实例的终结、对象什么时候符合垃圾回收的条件、GC Scope 示例程序、GC OutOfMemoryError的示例
53.垃圾回收算法的實(shí)現(xiàn)原理
53.1.目錄
53.2.啟動(dòng)Java垃圾回收
53.3.Java垃圾回收過程
53.4.垃圾回收中實(shí)例的終結(jié)
53.5.對象什么時(shí)候符合垃圾回收的條件?
53.5.1.GC Scope 示例程序
53.5.2.GC OutOfMemoryError 的示例程序。
53.垃圾回收算法的實(shí)現(xiàn)原理
http://www.importnew.com/13493.html
53.1.目錄
1.垃圾回收介紹
2.垃圾回收是如何工作的?
3.垃圾回收的類別
4.垃圾回收監(jiān)視和分析
本教程是為了理解基本的Java垃圾回收以及它是如何工作的。這是垃圾回收教程系列的第二部分。希望你已經(jīng)讀過了第一部分:《Java 垃圾回收介紹》。
Java 垃圾回收是一項(xiàng)自動(dòng)化的過程,用來管理程序所使用的運(yùn)行時(shí)內(nèi)存。通過這一自動(dòng)化過程,JVM 解除了程序員在程序中分配和釋放內(nèi)存資源的開銷。
53.2.啟動(dòng)Java垃圾回收
作為一個(gè)自動(dòng)的過程,程序員不需要在代碼中顯示地啟動(dòng)垃圾回收過程。System.gc()和Runtime.gc()用來請求JVM啟動(dòng)垃圾回收。
雖然這個(gè)請求機(jī)制提供給程序員一個(gè)啟動(dòng) GC 過程的機(jī)會(huì),但是啟動(dòng)由 JVM負(fù)責(zé)。JVM可以拒絕這個(gè)請求,所以并不保證這些調(diào)用都將執(zhí)行垃圾回收。啟動(dòng)時(shí)機(jī)的選擇由JVM決定,并且取決于堆內(nèi)存中Eden區(qū)是否可用。JVM將這個(gè)選擇留給了Java規(guī)范的實(shí)現(xiàn),不同實(shí)現(xiàn)具體使用的算法不盡相同。
毋庸置疑,我們知道垃圾回收過程是不能被強(qiáng)制執(zhí)行的。我剛剛發(fā)現(xiàn)了一個(gè)調(diào)用System.gc()有意義的場景。通過這篇文章了解一下適合調(diào)用System.gc() 這種極端情況。
53.3.Java垃圾回收過程
垃圾回收是一種回收無用內(nèi)存空間并使其對未來實(shí)例可用的過程。
Eden 區(qū):當(dāng)一個(gè)實(shí)例被創(chuàng)建了,首先會(huì)被存儲(chǔ)在堆內(nèi)存年輕代的 Eden 區(qū)中。
注意:如果你不能理解這些詞匯,我建議你閱讀這篇 垃圾回收介紹 ,這篇教程詳細(xì)地介紹了內(nèi)存模型、JVM 架構(gòu)以及這些術(shù)語。
Survivor 區(qū)(S0 和 S1):作為年輕代 GC(Minor GC)周期的一部分,存活的對象(仍然被引用的)從 Eden 區(qū)被移動(dòng)到 Survivor 區(qū)的 S0 中。類似的,垃圾回收器會(huì)掃描 S0 然后將存活的實(shí)例移動(dòng)到 S1 中。
(譯注:此處不應(yīng)該是Eden和S0中存活的都移到S1么,為什么會(huì)先移到S0再從S0移到S1?)
死亡的實(shí)例(不再被引用)被標(biāo)記為垃圾回收。根據(jù)垃圾回收器(有四種常用的垃圾回收器,將在下一教程中介紹它們)選擇的不同,要么被標(biāo)記的實(shí)例都會(huì)不停地從內(nèi)存中移除,要么回收過程會(huì)在一個(gè)單獨(dú)的進(jìn)程中完成。
老年代: 老年代(Old or tenured generation)是堆內(nèi)存中的第二塊邏輯區(qū)。當(dāng)垃圾回收器執(zhí)行Minor GC周期時(shí),在S1 Survivor區(qū)中的存活實(shí)例將會(huì)被晉升到老年代,而未被引用的對象被標(biāo)記為回收。
老年代 GC(Major GC):相對于Java垃圾回收過程,老年代是實(shí)例生命周期的最后階段。Major GC 掃描老年代的垃圾回收過程。如果實(shí)例不再被引用,那么它們會(huì)被標(biāo)記為回收,否則它們會(huì)繼續(xù)留在老年代中。
內(nèi)存碎片:一旦實(shí)例從堆內(nèi)存中被刪除,其位置就會(huì)變空并且可用于未來實(shí)例的分配。這些空出的空間將會(huì)使整個(gè)內(nèi)存區(qū)域碎片化。為了實(shí)例的快速分配,需要進(jìn)行碎片整理。基于垃圾回收器的不同選擇,回收的內(nèi)存區(qū)域要么被不停地被整理,要么在一個(gè)單獨(dú)的GC進(jìn)程中完成。
53.4.垃圾回收中實(shí)例的終結(jié)
在釋放一個(gè)實(shí)例和回收內(nèi)存空間之前,Java 垃圾回收器會(huì)調(diào)用實(shí)例各自的 finalize() 方法,從而該實(shí)例有機(jī)會(huì)釋放所持有的資源。雖然可以保證 finalize() 會(huì)在回收內(nèi)存空間之前被調(diào)用,但是沒有指定的順序和時(shí)間。多個(gè)實(shí)例間的順序是無法被預(yù)知,甚至可能會(huì)并行發(fā)生。程序不應(yīng)該預(yù)先調(diào)整實(shí)例之間的順序并使用 finalize() 方法回收資源。
?任何在 finalize過程中未被捕獲的異常會(huì)自動(dòng)被忽略,然后該實(shí)例的 finalize 過程被取消。
?JVM 規(guī)范中并沒有討論關(guān)于弱引用的垃圾回收機(jī)制,也沒有很明確的要求。具體的實(shí)現(xiàn)都由實(shí)現(xiàn)方?jīng)Q定。
?垃圾回收是由一個(gè)守護(hù)線程完成的。
53.5.對象什么時(shí)候符合垃圾回收的條件?
?所有實(shí)例都沒有活動(dòng)線程訪問。
?沒有被其他任何實(shí)例訪問的循環(huán)引用實(shí)例。
Java 中有不同的引用類型。判斷實(shí)例是否符合垃圾收集的條件都依賴于它的引用類型。
| 強(qiáng)引用(Strong Reference) | 不符合垃圾收集 |
| 軟引用(Soft Reference) | 垃圾收集可能會(huì)執(zhí)行,但會(huì)作為最后的選擇 |
| 弱引用(Weak Reference) | 符合垃圾收集 |
| 虛引用(Phantom Reference) | 符合垃圾收集 |
在編譯過程中作為一種優(yōu)化技術(shù),Java編譯器能選擇給實(shí)例賦 null 值,從而標(biāo)記實(shí)例為可回收。
class Animal {public static void main(String[] args) {Animal lion = new Animal();System.out.println("Main is completed.");}protected void finalize() {System.out.println("Rest in Peace!");} }在上面的類中,lion 對象在實(shí)例化行后從未被使用過。因此 Java 編譯器作為一種優(yōu)化措施可以直接在實(shí)例化行后賦值lion = null。因此,即使在 SOP 輸出之前, finalize 函數(shù)也能夠打印出 ‘Rest in Peace!’。我們不能證明這確定會(huì)發(fā)生,因?yàn)樗蕾嘕VM的實(shí)現(xiàn)方式和運(yùn)行時(shí)使用的內(nèi)存。然而,我們還能學(xué)習(xí)到一點(diǎn):如果編譯器看到該實(shí)例在未來再也不會(huì)被引用,能夠選擇并提早釋放實(shí)例空間。
?關(guān)于對象什么時(shí)候符合垃圾回收有一個(gè)更好的例子。實(shí)例的所有屬性能被存儲(chǔ)在寄存器中,隨后寄存器將被訪問并讀取內(nèi)容。無一例外,這些值將被寫回到實(shí)例中。雖然這些值在將來能被使用,這個(gè)實(shí)例仍然能被標(biāo)記為符合垃圾回收。這是一個(gè)很經(jīng)典的例子,不是嗎?
?當(dāng)被賦值為null時(shí),這是很簡單的一個(gè)符合垃圾回收的示例。當(dāng)然,復(fù)雜的情況可以像上面的幾點(diǎn)。這是由 JVM 實(shí)現(xiàn)者所做的選擇。目的是留下盡可能小的內(nèi)存占用,加快響應(yīng)速度,提高吞吐量。為了實(shí)現(xiàn)這一目標(biāo), JVM 的實(shí)現(xiàn)者可以選擇一個(gè)更好的方案或算法在垃圾回收過程中回收內(nèi)存空間。
?當(dāng) finalize() 方法被調(diào)用時(shí),JVM 會(huì)釋放該線程上的所有同步鎖。
53.5.1.GC Scope 示例程序
Class GCScope {GCScope t;static int i = 1;public static void main(String args[]) {GCScope t1 = new GCScope();GCScope t2 = new GCScope();GCScope t3 = new GCScope();// No Object Is Eligible for GCt1.t = t2; // No Object Is Eligible for GCt2.t = t3; // No Object Is Eligible for GCt3.t = t1; // No Object Is Eligible for GCt1 = null;// No Object Is Eligible for GC (t3.t still has a reference to t1)t2 = null;// No Object Is Eligible for GC (t3.t.t still has a reference to t2)t3 = null;// All the 3 Object Is Eligible for GC (None of them have a reference.// only the variable t of the objects are referring each other in a// rounded fashion forming the Island of objects with out any external// reference)}protected void finalize() {System.out.println("Garbage collected from object" + i);i++;}class GCScope {GCScope t;static int i = 1;public static void main(String args[]) {GCScope t1 = new GCScope();GCScope t2 = new GCScope();GCScope t3 = new GCScope();// 沒有對象符合GCt1.t = t2; // 沒有對象符合GCt2.t = t3; // 沒有對象符合GCt3.t = t1; // 沒有對象符合GCt1 = null;// 沒有對象符合GC (t3.t 仍然有一個(gè)到 t1 的引用)t2 = null;// 沒有對象符合GC (t3.t.t 仍然有一個(gè)到 t2 的引用)t3 = null;// 所有三個(gè)對象都符合GC (它們中沒有一個(gè)擁有引用。// 只有各對象的變量 t 還指向了彼此,// 形成了一個(gè)由對象組成的環(huán)形的島,而沒有任何外部的引用。)}protected void finalize() {System.out.println("Garbage collected from object" + i);i++;}53.5.2.GC OutOfMemoryError 的示例程序
GC并不保證內(nèi)存溢出問題的安全性,粗心寫下的代碼會(huì)導(dǎo)致 OutOfMemoryError。
import java.util.LinkedList; import java.util.List;public class GC {public static void main(String[] main) {List l = new LinkedList();// Enter infinite loop which will add a String to the list: l on each// iteration.do {l.add(new String("Hello, World"));} while (true);} }輸出:
Exception in thread "main" java.lang.OutOfMemoryError: Java heap spaceat java.util.LinkedList.linkLast(LinkedList.java:142)at java.util.LinkedList.add(LinkedList.java:338)at com.javapapers.java.GCScope.main(GCScope.java:12)接下來是垃圾收集系列教程的第三部分,我們將會(huì)看到常用的 不同 的Java垃圾收集器。
總結(jié)
以上是生活随笔為你收集整理的53.垃圾回收算法的实现原理、启动Java垃圾回收、Java垃圾回收过程、垃圾回收中实例的终结、对象什么时候符合垃圾回收的条件、GC Scope 示例程序、GC OutOfMemoryError的示例的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 老公姓陈老婆姓黄取什么网名?
- 下一篇: 60.Java 代码编译和执行的整个过程