自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

細(xì)述 Java垃圾回收機制→How Java Garbage Collection Works?

開發(fā) 后端
Java垃圾回收是一個自動運行的管理程序運行時使用的內(nèi)存的進程。通過GC的自動執(zhí)行JVM將程序員從申請和釋放內(nèi)存的繁重操作中解放出來。

這是垃圾回收機制系列文章的第二篇。希望您已經(jīng)讀過了***部分Java垃圾回收簡介。

Java垃圾回收是一個自動運行的管理程序運行時使用的內(nèi)存的進程。通過GC的自動執(zhí)行JVM將程序員從申請和釋放內(nèi)存的繁重操作中解放出來。

Java垃圾回收GC初始化

作為一個自動執(zhí)行的進程,程序員不需要在代碼中主動初始化GC。Java提供了System.gc()和Runtime.gc()這兩個hook來請求JVM調(diào)用GC進程。

盡管要求系統(tǒng)機制給程序員提供調(diào)用GC的機會,但是實際上這是由JVM負(fù)責(zé)決定的。JVM可以選擇拒絕啟動GC的請求,因此并不保證這些請求會真的調(diào)用垃圾回收。這是JVM基于內(nèi)存堆空間的Eden區(qū)的使用情況做出的決定。JVM規(guī)范將這個選擇權(quán)利留給了各個JVM的具體實現(xiàn),因此實際上JVM是如何選擇的視不同JVM的實現(xiàn)而定(不過要記住的是,不能依賴于這兩個方法的調(diào)用,它們是不被保證執(zhí)行的)。

毫無疑問的是,我們知道垃圾回收進程是不能強制執(zhí)行的。不過我剛發(fā)現(xiàn)一個調(diào)用System.gc()確實有意義的場景??聪逻@篇文章你就會了解System.gc()調(diào)用是可用的這個特殊的場景。

Java 垃圾回收進程

垃圾回收是一個回收不再使用的內(nèi)存空間并將它變成能夠為將來的實例使用的過程。

 

Eden Space:當(dāng)一個實例被創(chuàng)建的時候,它最初被存放在堆內(nèi)存空間的年輕代的Eden區(qū)中。

注意:如果您不太理解這些術(shù)語,建議您先看下介紹內(nèi)存模型、JVM架構(gòu)及這些術(shù)語的詳細(xì)解釋的文章:garbage-collection-introduction-tutorial

Survivor Space(S0 和S1):作為minor回收周期的一部分,還活著的對象(還有引用指向它)被從eden區(qū)中移動到survivor空間S0。同樣的,垃圾回收器掃描S0并將活著的實例移動到S1。

無用的對象(沒有引用指向)被標(biāo)記并回收。垃圾回收器(有四種可用的垃圾回收器,將在下一篇文章中介紹)決定這些被標(biāo)記的實例是在掃描的過程中移出內(nèi)存還是在另外獨立的遷移進程中執(zhí)行。

Old Generation:老年代或者***代是堆內(nèi)存的第二個邏輯部分。當(dāng)垃圾回收器在做minor GC周期中,S1 survivor區(qū)中還活著的實例會被提升到老年代中。S1區(qū)中不再被引用的對象被標(biāo)記并清除。

Major GC:在Java垃圾回收過程中實例生命周期的***一個階段。Major GC在垃圾回收過程中掃描屬于Old Generation部分的堆內(nèi)存。如果實例沒有被任何引用關(guān)聯(lián),它們將被標(biāo)記、清除;如果它們還被引用關(guān)聯(lián)著,則將繼續(xù)存留在old generation。

Memory

Fragmentation:一旦實例從堆內(nèi)存中刪除了,它們原來的位置將空出來給以后分配實例使用。顯然這些空閑空間很容易在內(nèi)存空間中產(chǎn)生碎片。為了能夠更快地分配實例地址,需要對內(nèi)存做去碎片化操作。根據(jù)不同垃圾回收器的策略,被回收的內(nèi)存將在回收的過程同時或者在GC另外獨立的過程中壓縮整合。

垃圾回收過程中的對象銷毀–Finalization

就在移除一個對象并回收它的內(nèi)存空間之前,Java垃圾回收器將會調(diào)用各個實例的finalize()方法,這樣實例對象就有機會可以釋放掉它占用的資源。盡管finalize()方法是保證在回收內(nèi)存空間之前執(zhí)行的,但是對具體的執(zhí)行時間和執(zhí)行順序是沒有任何保證的。多個實例之間的finalize()執(zhí)行順序是不能提前預(yù)知的,甚至有可能它們是并行執(zhí)行的。程序不應(yīng)該預(yù)先假設(shè)實例執(zhí)行finalize()的方法,也不應(yīng)該使用finalize()方法來回收資源。

  1. 在finalize過程中拋出的任何異常都默認(rèn)被忽略掉了,同時對象的銷毀過程被取消
  2. JVM規(guī)范并沒有討論關(guān)于弱引用的垃圾回收,這是明確聲明的。具體的細(xì)節(jié)留給實現(xiàn)者決定。
  3. 垃圾回收是由守護進程執(zhí)行的

對象何時變成可被垃圾回收的?

  • 所有不能被活著的線程到達實例
  • 不能被其他對象到達的循環(huán)引用對象 Java中有多種不同的引用類型。實例的可回收性取決于它的引用類型。

在編譯過程中Java編譯器有個優(yōu)化機制,編譯器可以選擇將null賦值給一個實例,這樣就將這個實例標(biāo)志為可被回收的。

  1. class Animal { 
  2.        public static void main(String[] args) { 
  3.            Animal lion = new Animal(); 
  4.            System.out.println("Main is completed."); 
  5.        } 
  6.  
  7.        protected void finalize() { 
  8.            System.out.println("Rest in Peace!"); 
  9.        } 
  10.    } 

在上面這個類中,實例lion在除了初始化那一行在其他地方都沒有被使用到。因此作為一種優(yōu)化方法,Java編譯器可以在初始化那一行后面立即賦值lion = null。這樣finlizer可能會在Main方法的SOP之前打印結(jié)果。

  1. Rest in Peace! 
  2.  
  3. Main is completed. 

但結(jié)果的順序是不確定的,它取決于JVM的實現(xiàn)以及運行時的內(nèi)存使用情況。從中我們能知道的一點是:編譯器在發(fā)現(xiàn)一個實例的之后的程序中不再被引用時可以選擇提前釋放實例內(nèi)存。

  • 這里有個實例何時變成可回收更好的例子。實例所有的屬性可以被存儲在寄存器中之后可以從寄存器中讀取這些屬性值,且未來在任何情況下都不會將值寫回到實例對象中。這樣盡管這個實例在未來還是被使用到了,但是實例對象依然可以被標(biāo)記為可回收的。
  • 何時能被垃圾回收可以簡單到僅僅認(rèn)為在賦值為null的時候也可以復(fù)雜到如上面那一點所說的那樣。JVM的實現(xiàn)者會做一些取舍。其目標(biāo)都是希望留下最少的痕跡,提高響應(yīng)時間增大吞吐量。為了能夠達到這些目的,JVM實現(xiàn)者可以在垃圾回收中選擇更好的模式或算法來回收內(nèi)存。
  • 當(dāng)finalize()被調(diào)用的時候,JVM釋放掉當(dāng)前線程的所有同步塊。

Example Program for GC Scope

  1. class GCScope { 
  2.         GCScope t; 
  3.         static int i = 1; 
  4.  
  5.         public static void main(String args[]) { 
  6.             GCScope t1 = new GCScope(); 
  7.             GCScope t2 = new GCScope(); 
  8.             GCScope t3 = new GCScope(); 
  9.             //沒有任何一個對象是可以被GC的 
  10.             t1.t = t2;//沒有任何一個對象是可以被GC的 
  11.             t2.t = t3;//沒有任何一個對象是可以被GC的 
  12.             t3.t = t1;//沒有任何一個對象是可以被GC的 
  13.  
  14.             t1 = null;//沒有任何一個對象是可以被GC的,t3.t還有對t1的引用 
  15.  
  16.             t2 = null;//沒有任何一個對象是可以被GC的,t3.t.t還有對t2的引用 
  17.             t3 = null;//所有3個對象都可以被GC(沒有一個被引用了) 
  18.             //只有各個對象的變量t互相循環(huán)引用形成了一個孤立的引用環(huán),而沒有外部引用 
  19.         } 
  20.  
  21.         protected void finalize() { 
  22.             System.out.println("Garbage collected from boject" + i); 
  23.             i++; 
  24.         } 
  25.     } 

Example Program for GC OutOfMemoryError

垃圾回收機制并不保證發(fā)生內(nèi)存溢出時的安全,事實上內(nèi)存溢出將會導(dǎo)致程序的崩潰,拋出OutOfMemoryError。import java.util.LinkedList; 

  1. import java.util.List; 
  2.  
  3. public class GC { 
  4.     public static void main(String[] args[]) { 
  5.         List l = new LinkedList(); 
  6.         //進入內(nèi)部***循環(huán)直接向鏈表中不斷添加元素 
  7.         do { 
  8.             l.add(new String("Hello, World!"); 
  9.         } while (true); 
  10.     } 

 Output

  1. Exception in thread "main" java.lang.OutOfMemoryError: Java heap space 
  2.     at java.util.LinkedList.linkLast(LinkedList.java:142) 
  3.     at java.util.LinkedList.add(LinkedList.java:338) 
  4.     at com.javapapers.java.GCScope.main(GCScope.java:12) 

 

 

責(zé)任編輯:龐桂玉 來源: segmentfault
相關(guān)推薦

2016-08-11 14:26:29

Java垃圾回收機制內(nèi)存分配

2016-08-11 15:46:58

Java垃圾回收機制原理

2016-08-11 15:02:54

Java垃圾回收機制內(nèi)存

2009-06-23 14:15:00

Java垃圾回收

2011-07-04 16:48:56

JAVA垃圾回收機制GC

2011-06-28 12:39:34

Java垃圾回收

2015-06-04 09:38:39

Java垃圾回收機

2010-09-26 14:08:41

Java垃圾回收

2010-10-13 10:24:38

垃圾回收機制JVMJava

2010-09-25 15:33:19

JVM垃圾回收

2017-03-03 09:26:48

PHP垃圾回收機制

2017-08-17 15:40:08

大數(shù)據(jù)Python垃圾回收機制

2021-11-05 15:23:20

JVM回收算法

2024-10-28 13:18:54

2021-05-27 21:47:12

Python垃圾回收

2010-09-25 15:26:12

JVM垃圾回收

2010-09-16 15:10:24

JVM垃圾回收機制

2017-06-12 17:38:32

Python垃圾回收引用

2021-02-26 05:24:35

Java垃圾回收

2021-12-07 08:01:33

Javascript 垃圾回收機制前端
點贊
收藏

51CTO技術(shù)棧公眾號