java回收機制
Ⅰ java中垃圾回收機制的原理
java中垃圾回收機制的原理
推薦一篇文章:
對高性能JAVA代碼之內存管理
更甚者你寫的代碼,GC根本就回收不了,直接系統掛掉。GC是一段程序,不是智能,他只回收他認為的垃圾,而不是回收你認為的垃圾。
GC垃圾回收:
Grabage Collection相信學過JAVA的人都知道這個是什麼意思。但是他是如何工作的呢?
首先,JVM在管理內存的時候對於變數的管理總是分新對象和老對象。新對象也就是開發者new出來的對象,但是由於生命周期短,那麼他佔用的內存並不是馬上釋放,而是被標記為老對象,這個時候該對象還是要存在一段時間。然後由JVM決定他是否是垃圾對象,並進行回收。
所以我們可以知道,垃圾內存並不是用完了馬上就被釋放,所以就會產生內存釋放不及時的現象,從而降低了內存的使用。而當程序浩大的時候。這種現象更為明顯,並且GC的工作也是需要消耗資源的。所以,也就會產生內存浪費。
JVM中的對象生命周期里談內存回收:
對象的生命周期一般分為7個階段:創建階段,應用階段,不可視階段,不可到達階段,可收集階段,終結階段,釋放階段。
創建階段:首先大家看一下,如下兩段代碼:
test1:
for( int i=0; i《10000; i++)
Object obj=new Object();
test2:
Object obj=null;
for( int i=0; i《10000; i++)
obj=new Object();
這兩段代碼都是相同的功能,但是顯然test2的性能要比test1性能要好,內存使用率要高,這是為什麼呢?原因很簡單,test1每次執行for循環都要創建一個Object的臨時對象,但是這些臨時對象由於JVM的GC不能馬上銷毀,所以他們還要存在很長時間,而test2則只是在內存中保存一份對象的引用,而不必創建大量新臨時變數,從而降低了內存的使用。
另外不要對同一個對象初始化多次。例如:
public class A{
private Hashtable table = new Hashtable();
public A(){ table = new Hashtable();
// 這里應該去掉,因為table已經被初始化。
}
這樣就new了兩個Hashtable,但是卻只使用了一個。另外一個則沒有被引用。而被忽略掉。浪費了內存。並且由於進行了兩次new操作。也影響了代碼的執行速度。
應用階段:即該對象至少有一個引用在維護他。
不可視階段:即超出該變數的作用域。這里有一個很好的做法,因為JVM在GC的時候並不是馬上進行回收,而是要判斷對象是否被其他引用在維護。所以,這個時候如果我們在使用完一個對象以後對其obj=null或者obj.doSomething()操作,將其標記為空,可以幫助JVM及時發現這個垃圾對象。
不可到達階段:就是在JVM中找不到對該對象的直接或者間接的引用。
可收集階段,終結階段,釋放階段:此為回收器發現該對象不可到達,finalize方法已經被執行,或者對象空間已被重用的時候。
JAVA的析構方法:
可能不會有人相信,JAVA有析構函數? 是的,有。因為JAVA所有類都繼承至Object類,而finalize就是Object類的一個方法,這個方法在JAVA中就是類似於C++析構函數。一般來說可以通過重載finalize方法的形式才釋放類中對象。如:
public class A{
public Object a;
public A(){ a = new Object ;}
protected void finalize() throws java.lang.Throwable{
a = null; // 標記為空,釋放對象
super.finalize(); // 遞歸調用超類中的finalize方法。
}
}
當然,什麼時候該方法被調用是由JVM來決定的。..。..。..。..。..。..。..。.
一般來說,我們需要創建一個destory的方法來顯式的調用該方法。然後在finalize也對該方法進行調用,實現雙保險的做法。
由於對象的創建是遞歸式的,也就是先調用超級類的構造,然後依次向下遞歸調用構造函數,所以應該避免在類的構造函數中初始化變數,這樣可以避免不必要的創建對象造成不必要的內存消耗。當然這里也就看出來介面的優勢。
數組的創建:
由於數組需要給定一個長度,所以在不確定數據數量的時候經常會創建過大,或過小的數組的現象。造成不必要的內存浪費,所以可以通過軟引用的方式來告訴JVM及時回收該內存。(軟引用,具體查資料)。
例如:
Object obj = new char[10000000000000000];
SoftReference ref = new SoftReference(obj);
共享靜態存儲空間:
我們都知道靜態變數在程序運行期間其內存是共享的,因此有時候為了節約內存工件,將一些變數聲明為靜態變數確實可以起到節約內存空間的作用。但是由於靜態變數生命周期很長,不易被系統回收,所以使用靜態變數要合理,不能盲目的使用。以免適得其反。
因此建議在下面情況下使用:
1,變數所包含的對象體積較大,佔用內存過多。
2,變數所包含對象生命周期較長。
3,變數所包含數據穩定。
4,該類的對象實例有對該變數所包含的對象的共享需求。(也就是說是否需要作為全局變數)。
對象重用與GC:
有的時候,如資料庫操作對象,一般情況下我們都需要在各個不同模塊間使用,所以這樣的對象需要進行重用以提高性能。也有效的避免了反復創建對象引起的性能下降。
一般來說對象池是一個不錯的注意。如下:
public abstarct class ObjectPool{
private Hashtable locked,unlocked;
private long expirationTime;
abstract Object create();
abstract void expire( Object o);
abstract void validate( Object o);
synchronized Object getObject(){。..};
synchronized void freeObject(Object o){。..};
這樣我們就完成了一個對象池,我們可以將通過對應的方法來存取刪除所需對象。來維護這快內存提高內存重用。
當然也可以通過調用System.gc()強制系統進行垃圾回收操作。當然這樣的代價是需要消耗一些cpu資源。
不要提前創建對象:
盡量在需要的時候創建對象,重復的分配,構造對象可能會因為垃圾回收做額外的工作降低性能。
JVM內存參數調優:
強制內存回收對於系統自動的內存回收機制會產生負面影響,會加大系統自動回收的處理時間,所以應該盡量避免顯式使用System.gc(),
JVM的設置可以提高系統的性能。例如:
java -XX:NewSize=128m -XX:MaxNewSize=128m -XX:SurvivorRatio=8 -Xms512m -Xmx512m
具體可以查看java幫助文檔。我們主要介紹程序設計方面的性能提高。
JAVA程序設計中有關內存管理的其他經驗:
根據JVM內存管理的工作原理,可以通過一些技巧和方式讓JVM做GC處理時更加有效。,從而提高內存使用和縮短GC的執行時間。
1,盡早釋放無用對象的引用。即在不使用對象的引用後設置為空,可以加速GC的工作。(當然如果是返回值。..。.)
2,盡量少用finalize函數,此函數是JAVA給程序員提供的一個釋放對象或資源的機會,但是卻會加大GC工作量。
3,如果需要使用到圖片,可以使用soft應用類型,它可以盡可能將圖片讀入內存而不引起OutOfMemory.
4,注意集合數據類型的數據結構,往往數據結構越復雜,GC工作量更大,處理更復雜。
5,盡量避免在默認構造器(構造函數)中創建,初始化大量的對象。
6,盡量避免強制系統做垃圾回收。會增加系統做垃圾回收的最終時間降低性能。
7,盡量避免顯式申請數組,如果不得不申請數組的話,要盡量准確估算數組大小。
8,如果在做遠程方法調用。要盡量減少傳遞的對象大小。或者使用瞬間值避免不必要數據的傳遞。
9,盡量在合適的情況下使用對象池來提高系統性能減少內存開銷,當然,對象池不能過於龐大,會適得其反.
Ⅱ java回收機制的原理是什麼
垃圾回收是java與c/c++的最大不同。有了jvm的自動垃圾收集機制,就可以讓程序員專注於程序邏輯開發,而不是花費大量的時間是考慮變數應該在什麼時候去釋放。
首先我們要知道要,jvm是如何判斷一個對象已經變成了」垃圾「的呢?
一般用的是兩個方法:
1)引用記數法:
為每個對象保存一個引用的數量,每增加一個引用這個值就加1,每減少一個引用就減1.如果這個記數變為0了,就說明這個對象已經不再被使用了。那麼jvm就認為這個對象是可以回收的了。
但是這個方法有一個缺點,就是無法解決循環引用的問題。A引用B,B也引用A,如果A,B兩個對象都不再被使用了,那麼這兩個對象其實都是可以被回收的,但是他們的引用記數不為0.所以用這個辦法就沒有辦法回收了。
2)根搜索演算法:
從一系列的」GC Roots「對象開始向下搜索,搜索走過的路徑稱為引用鏈。當一個對象到」GC Roots「之間沒有引用鏈時,被稱為引用不可達。引用不可到的對象被認為是可回收的對象。
java中可以當做為」GC Roots「對象的包括:
1:jvm虛擬機棧(棧幀中的局部變數表)中引用的對象
2:方法區中的類靜態屬性引用的對象
3:常量池中的常量引用的對象
4:本地方法棧JNI(native方法)中的引用的對象
Ⅲ java什麼是垃圾回收機制
1、回收的內容是new出來的對象所佔內存;
2、垃圾回收只與內存有關,清理內存外的資源依靠finalize()方法。垃圾回收機制在回收某個對象的內存前會調用該對象的finalize()方法。
3、強制系統垃圾回收的方式(通過程序通知系統進行垃圾回收,但系統還不一定進行垃圾回收):
System.gc();
Runtime.getRuntime().gc();
- 4、垃圾回收以單獨的線程在後台運行,為減少虛擬機額外消耗,一般在內存不足時會進行垃圾回收,所以就算強制系統垃圾回收,垃圾回收也不一定發生;
5、對象在內存中的狀態有可達狀態、可恢復狀態、不可達狀態,當處於可恢復狀態時可能會進行垃圾回收。
Ⅳ java中垃圾回收機制的原理是什麼
GC的工作原理: 引用計數,標記復制"引用計數"是一種簡單但速度很慢的垃圾回收技術.所有對象都有一個引用計數器,當有引用連接時計數器加1,當引用離開作用域時或者被置於NULL時,計數器-1,垃圾回收器會在所有包含對象引用的列表上進行遍歷,當發現某個對象的引用計數為0時,就釋放佔用的空間."標記復制"的運行機制,垃圾回收器遍歷包含所有引用的列表,當發現存活的對象引用時做上標記,這樣當遍歷完所有對象引用並做上標記的時候,執行垃圾回收,將沒有標記的對象堆空間釋放.
垃圾回收機制的優點:Java的垃圾回收機制使得java程序員不用擔心內存空間的分配,減少了內存溢出.但同時也犧牲了一定的性能.
Ⅳ Java語言的內存回收機制是什麼
內存回收機制就是對象沒有引用就會回收
其實Java垃圾回收主要做的是兩件事:1)內存回收 2)碎片整理
垃圾回收演算法
1)串列回收(只用一個CPU)和並行回收(多個CPU才有用):串列回收是不管系統有多少個CPU,始終只用一個CPU來執行垃圾回收操作,而並行回收就是把整個回收工作拆分成多個部分,每個部分由一個CPU負責,從而讓多個CPU並行回收。並行回收的執行效率很高,但復雜度增加,另外也有一些副作用,如內存隨便增加。
2)並發執行和應用程序停止 :應用程序停止(Stop-the-world)顧名思義,其垃圾回收方式在執行垃圾回收的同時會導致應用程序的暫停。並發執行的垃圾回收雖然不會導致應用程序的暫停,但由於並發執行垃圾需要解決和應用程序的執行沖突(應用程序可能在垃圾回收的過程修改對象),因此並發執行垃圾回收的系統開銷比Stop-the-world高,而且執行時需要更多的堆內存。
3)壓縮和不壓縮和復制 :
①支持壓縮的垃圾回收器(標記-壓縮 = 標記清除+壓縮)會把所有的可達對象搬遷到一起,然後將之前佔用的內存全部回收,減少了內存碎片。
②不壓縮的垃圾回收器(標記-清除)要遍歷兩次,第一次先從跟開始訪問所有可達對象,並將他們標記為可達狀態,第二次便利整個內存區域,對未標記可達狀態的對象進行回收處理。這種回收方式不壓縮,不需要額外內存,但要兩次遍歷,會產生碎片
③復制式的垃圾回收器:將堆內存分成兩個相同空間,從根(類似於前面的有向圖起始頂點)開始訪問每一個關聯的可達對象,將空間A的全部可達對象復制到空間B,然後一次性回收空間A。對於該演算法而言,因為只需訪問所有的可達對象,將所有的可達對象復制走之後就直接回收整個空間,完全不用理會不可達對象,所以遍歷空間的成本較小,但需要巨大的復製成本和較多的內存。
看看這個:http://developer.51cto.com/art/201304/387381_1.htm
Ⅵ java垃圾回收機制
由於使用new運算符來為對象動態地分配內存,你可能想知道這些對象是如何撤消的
以及他們的內存在以後的重新分配時是如何被釋放的。在一些語言,例如C++中,用delete
運算符來手工地釋放動態分配的對象的內存。Java使用一種不同的、自動地處理重新分配
內存的辦法:垃圾回收( garbage collection)技術,它是這樣工作的:當一個對象的引用不存
在時,則該對象被認為是不再需要的,它所佔用的內存就被釋放掉。它不像C++那樣需要
顯式撤消對象。垃圾回收只在你的程序執行過程中偶爾發生。它不會因為一個或幾個存在
的對象不再被使用而發生。況且,Java不同的運行時刻會產生各種不同的垃圾回收辦法,
但是對你編寫的大多數程序,你不必須考慮垃圾回收問題。
Ⅶ Java垃圾回收機制,按照什麼規則回收
運行垃圾收集的可能情況是:
1.堆可用內存不足
2.CPU空閑
垃圾回收的最佳做法?
用編程的方式,我們可以手動讓JVM通過調用System.gc()方法來運行垃圾回收。
當內存已滿,且堆上沒有對象可用於垃圾回收時,JVM可能會拋出OutOfMemoryException。
對象在被垃圾回收從堆上刪除之前,會運行finalize()方法。我們建議不要用finalize()方法寫任何代碼。
Ⅷ Java垃圾回收機制是什麼
垃圾是指:無用的對象或者引用
回收:清除其所佔內存
機制:自動發生或(gc())
Ⅸ java的垃圾回收機制是什麼 請詳細解釋
Java的垃圾回收機制是Java虛擬機提供的能力,用於在空閑時間以不定時的方式動態回收無任何引用的對象占據的內存空間。
Ⅹ java的垃圾回收機制是什麼
1、回收的內容是new出來的對象所佔內存;
2、垃圾回收只與內存有關,清理內存外的資源依靠finalize()方法。垃圾回收機制在回收某個對象的內存前會調用該對象的finalize()方法。
3、強制系統垃圾回收的方式(通過程序通知系統進行垃圾回收,但系統還不一定進行垃圾回收):
System.gc();
Runtime.getRuntime().gc();
- 4、垃圾回收以單獨的線程在後台運行,為減少虛擬機額外消耗,一般在內存不足時會進行垃圾回收,所以就算強制系統垃圾回收,垃圾回收也不一定發生;
5、對象在內存中的狀態有可達狀態、可恢復狀態、不可達狀態,當處於可恢復狀態時可能會進行垃圾回收。