1. 程式人生 > >java之finalization與GC

java之finalization與GC

轉載請註明出處

作者:小馬

java 中的GC(garbage collection)並不像C++的解構函式一樣每次物件被刪除時呼叫,事實上它是一種JVM(JAVA 虛擬機器)行為,JVM在它認為“合適”的情況下呼叫。這個所謂的合適情況,應用層其實不必考慮過多。可以認為GC呼叫的時機是隨機的。

finaliztion是個可以被應用層過載的函式,當GC回收一個物件時,它會先呼叫物件的這個函式然後再處理其它事情。所以應用可以過載這個函式,去做一下想在GC前收尾的工作(聽起來越來越像C++中的析構了,但是請注意呼叫時機)。

但是問題來了,GC本來就是記憶體回收了,應用還需要在finalization做什麼呢? 答案是大部分時候,什麼都不用做(也就是不需要過載)。只有在某些很特殊的情況下,比如你呼叫了一些native的方法(一般是C寫的),可以要在finaliztion裡去呼叫C的釋放函式。

下面這個程式碼示例,過載了finaliztion,但是僅僅是為了觀察GC的行為,類很簡單,

class Chair
{
	static boolean gcrun = false;
	static boolean f = false;
	static int created = 0;
	static int finalized = 0;
	
	int i;
	Chair() 
	{
		i = ++created;
		if(created == 47)
		{
			System.out.println("Created 47");
		}
	}
	
	public void finalize()
	{
		if(!gcrun)
		{
			gcrun = true;
			System.out.println("beginning to finalize after " +
					created + " chairs have been created");
		}
		if(i == 47)
		{
			System.out.println("finalizing chair #47, " +
					"setting flag to stop chair creation");
			f = true;
		}
		finalized++;
		if(finalized >= created)
		{
			System.out.println("all " + finalized + " finalized");
		}
	}
}

created和finalized用來跟蹤分別建立和回收了多少物件,而物件的成員i可以理解為每個物件的號碼,從程式碼上看,當號碼為47的物件被回收時,把f置為true,這樣main函式就不會建立新的Chair例項了,main函式如下:

public class Garbage 
{

	/**
	 * @param args
	 */
	public static void main(String[] args) 
	{
		while(!Chair.f)
		{
			new Chair();
			new String("to take up space");
		}
		
		System.out.println("after all chairs have been created:\n" +
				"total finalized = " + Chair.finalized);
		
		//optional arguments force garbage
		//collection & finalization
		if(args.length > 0)
		{
			if(args[0].equals("gc") ||
					args[0].equals("all"))
			{
				System.out.println("gc():");
				System.gc();
			}
			
			if(args[0].equals("finalize") ||
					args[0].equals("all"))
			{
				System.out.println("run finalization():");
				System.runFinalization();
			}
		}
		
		System.out.println("byte!");

	}

}


注意並不是說,建立了第47個物件時就開始回收,原因還是上面講的回收時機問題。所以當i==47時,可以已經建立了幾千個chair物件了。

輸出結果:

Created 47
beginning to finalize after 4691 chairs have been created
finalizing chair #47, setting flag to stop chair creation
after all chairs have been created:
total finalized = 6151
byte!


main函式中的System.runFinalization()和System.gc是做什麼的呢? 我個人的理解,這兩個函式分別是應用層向JVM發出一個訊號,告訴JVM,希望你能儘快的回收記憶體和呼叫物件的finaliztion方法,但是隻是一個請求,而JVM只保證會盡最大的努力執行,但是具體什麼時候執行以及會不會執行都是未知的。

相關推薦

javafinalizationGC

轉載請註明出處 作者:小馬 java 中的GC(garbage collection)並不像C++的解構函式一樣每次物件被刪除時呼叫,事實上它是一種JVM(JAVA 虛擬機器)行為,JVM在它認為“合適”的情況下呼叫。這個所謂的合適情況,應用層其實不必考慮過多。可

JavaFile遞歸

必須 文件的 nta 傳智 public 抽象 static accep 繼續 File類的使用和遞歸思想 File類 概述 文件: 存儲數據 文件夾: 管理文件與文件夾 構造方法 public File(String pathname) :通過將給定的路徑名字符串轉換為

java 記憶體溢位-gc

參考: https://www.jianshu.com/p/ddbd1e229c4c?from=groupmessage 感謝原作者 在日常中我們經常遇到這樣的錯誤:java.lang.OutOfMemoryError: Java heap space。 但是除了heap sp

Javaimport語句

寫的太細緻就會很囉嗦,回頭也看下去,我就通過看視訊簡單總結一下需要注意的地方。 沒有public的類只能在該包的內部使用,不能在包外使用。 包的名字就是其所在目錄的名字,包名字裡面的“ . ”表示的是資料夾的層次,“ . ”後面的名字表示的是前面包下的另

Java重寫過載

很久之前寫的部落格,忘記發了。。。 重寫(Override) 重寫是子類對父類的允許訪問的方法的實現過程進行重新編寫, 返回值和形參都不能改變。即外殼不變,核心重寫! 重寫的好處在於子類可以根據需要,定義特定於自己的行為。 再換一種簡單的說法:  父類與子類之間的多型性

Java過載覆蓋

有的時候,類的同一種功能有多種實現方式,到底採用哪種實現方式,取決於呼叫者給定的引數。例如我們最常用的System.out.println()能夠打印出任何資料型別的資料,它有多種實現方式。執行時,Java虛擬機器先判斷給定引數的型別,然後決定執行哪個println()方

javaBIONIO圖解

    java中網路通訊是通過Socket實現的,Socket分為ServerSocket與Socket兩類;ServerSocket用於服務端,可以通過accept監聽請求,監聽到請求後返回Socket,用於具體完成資料傳輸,而客戶端直接使用Socket發起請求並傳輸資料

java 裝箱拆箱的研究總結

今天看java JDK7的新特新語法糖的時候突然有提到裝箱與拆箱,就特地加深一下: 所謂裝箱:就是在程式碼編譯期將基本型別轉化為包裝型別,使其基本有型別具有物件特徵 所謂拆箱:與裝箱過程相反,就是把包裝型別轉為基本型別  自動裝箱/拆箱 就是程式碼在編譯根據程式碼的語法,

深入理解Java裝箱拆箱

### 一、Java資料型別 1、在說裝箱與拆箱之前,先說一下Java的基本資料型別,Java從資料型別上可以劃分為`值型別`與`引用型別`,值型別是`四類八種`,分別是: + 整數型:byte̵,short̵,int̵,long + 浮點型:float,double + 字元型:char + 布林型:bo

java虛擬機器記憶體分配新生代老年代GC

1. Java堆中各代分佈: 圖1:Java堆中各代分佈 Young:主要是用來存放新生的物件。 Old:主要存放應用程式中生命週期長的記憶體物件。 Permanent:是指記憶體的永久儲存區域,主要存放Class和Meta的資訊,Class在被 Load的時候被放入PermGen space區域. 它和

Java SE裝箱拆箱

fin valueof targe 單純 數值 test 構造 簡化 ble 對象包裝器、自動裝箱與拆箱 2016/11/30 晚 特點: 1.所有的基本類型都有一個包裝器類與之對應。[Integer,Boolean,Long,Character,Sh

Java學習(7):同步問題生產者消費者的問題

con runnable pop pre 標記 this auth style about 生產者生產饅頭,消費者消費饅頭。一個籃子,生產者往籃子中放饅頭,消費者從籃子中取饅頭。 /** * 這是一個籃子類 * * @author xcx * @time 2017

JavaStringBuffer和StringBuilder的差別聯系

-c 多線程 線程安全 java 線程不安全 而且 ring 字符 rac 2.StringBuilder,StringBuffer 字符串拼接時用這兩個類,效率高。節約內存。假設用字符串 "+"號拼接 性能差。而且浪費空間,

每天學一點ScalaScalaJava的區別?

scala java 函數式編程 A、Scala是編譯型語言,可以隨意調用Java代碼;B、 Scala函數式編程語言,在scala世界裏,函數才是一等公民;函數可以作為參數進行傳遞,可以賦值給變量,可以作為返回值進行返回scala中,具有嵌套函數、匿名函數、高階函數、偏函數scala支持閉包本

java內存管理GC機制(一)

大於 一個棧 es2017 記錄 高速 工作 限制 fin 不存在 計算機cpu運轉速度越來越快,硬盤遠遠跟不上cpu的讀寫速度,就設計可內存。隨著cpu的發展,內存的讀寫速度也跟不上cpu處理速度,就在每顆cpu上加入了高速緩存。在多處理器系統中,每個處理

java基礎篇nioaio

sre 非阻塞 只有一個 accept ava 使用步驟 截取 city writable 1.同步和異步 同步:指一個任務運行完以後接著運行下一個任務 異步:接到一個任務後開啟一個新的線程運行此任務,基本不占用原線程時間 2.阻塞與非阻塞 阻塞:多個線程同時訪問一份數據時

JAVA多線程volatile synchronized 的比較

@override effect process 棧空間 完成 內存可見性 沒有 hash 主從 一,volatile關鍵字的可見性 要想理解volatile關鍵字,得先了解下JAVA的內存模型,Java內存模型的抽象示意圖如下: 從圖中可以看出: ①每個線程都有一個自己的

Java集合Collection子類回顧

asn void 排序 dha 避免 bst 自然 我們 tip Java學習這麽久,打算這幾天回顧下java的基本知識點,首先是集合。 一、常用集合類關系圖 Collection   |___List  有序,可重復     |___ArrayList   底層數據結構是

Java常用類(三)StringBufferStringBuidler

lane 這一 eight cit 優先 simple bmp imp uid 前言   前面一篇給大家介紹了String類,這個我們經常會用到的一個類,那這一篇給大家分享的是StringBuffer與StringBuidler。等下我也會比較他們三個之間的區別 一、S

javaJVM學習--簡單了解GC算法

救贖 osgi -xms 查看類 nor blog 虛擬機棧 頻繁 lur JVM內存組成結構: (1)堆 所有通過new創建的對象都是在堆中分配內存,其大小可以通過-Xmx和-Xms來控制,堆被劃分為新生代和舊生代,新生代又被進一步劃分為Eden和Survivor