JAVA垃圾收集算法與內存泄露的解決方法
對於垃圾收集算法與內存泄露的問題,下面YJBYS小編爲大家整理了關於JAVA垃圾收集算法與內存泄露解決方法,希望對你有所幫助。
1.垃圾收集算法的核心思想
Java語言建立了垃圾收集機制,用以跟蹤正在使用的對象和發現並回收不再使用(引用)的對象。該機制可以有效防範動態內存分配中可能發生的兩個危險:因內存垃圾過多而引發的內存耗盡,以及不恰當的內存釋放所造成的內存非法引用。
垃圾收集算法的核心思想是:對虛擬機可用內存空間,即堆空間中的對象進行識別,如果對象正在被引用,那麼稱其爲存活對象,反之,如果對象不再被引用,則爲垃圾對象,可以回收其佔據的空間,用於再分配。垃圾收集算法的選擇和垃圾收集系統參數的合理調節直接影響着系統性能,因此需要開發人員做比較深入的瞭解。
2.觸發主GC(Garbage Collector)的條件
JVM進行次GC的頻率很高,但因爲這種GC佔用時間極短,所以對系統產生的影響不大。更值得關注的是主GC的觸發條件,因爲它對系統影響很明顯。總的來說,有兩個條件會觸發主GC:
①當應用程序空閒時,即沒有應用線程在運行時,GC會被調用。因爲GC在優先級最低的線程中進行,所以當應用忙時,GC線程就不會被調用,但以下條件除外。
②Java堆內存不足時,GC會被調用。當應用線程在運行,並在運行過程中創建新對象,若這時內存空間不足,JVM就會強制地調用GC線程,以便回收內存用於新的分配。若GC一次之後仍不能滿足內存分配的要求,JVM會再進行兩次GC作進一步的嘗試,若仍無法滿足要求,則 JVM將報“out of memory”的錯誤,Java應用將停止。
由於是否進行主GC由JVM根據系統環境決定,而系統環境在不斷的變化當中,所以主GC的運行具有不確定性,無法預計它何時必然出現,但可以確定的是對一個長期運行的應用來說,其主GC是反覆進行的。
3.減少GC開銷的措施
根據上述GC的機制,程序的運行會直接影響系統環境的變化,從而影響GC的觸發。若不針對GC的特點進行設計和編碼,就會出現內存駐留等一系列負面影響。爲了避免這些影響,基本的原則就是儘可能地減少垃圾和減少GC過程中的開銷。具體措施包括以下幾個方面:
(1)不要顯式調用()
此函數建議JVM進行主GC,雖然只是建議而非一定,但很多情況下它會觸發主GC,從而增加主GC的頻率,也即增加了間歇性停頓的次數。
(2)儘量減少臨時對象的使用
臨時對象在跳出函數調用後,會成爲垃圾,少用臨時變量就相當於減少了垃圾的產生,從而延長了出現上述第二個觸發條件出現的時間,減少了主GC的機會。
(3)對象不用時最好顯式置爲Null
一般而言,爲Null的對象都會被作爲垃圾處理,所以將不用的對象顯式地設爲Null,有利於GC收集器判定垃圾,從而提高了GC的效率。
(4)儘量使用StringBuffer,而不用String來累加字符串(詳見blog另一篇文章JAVA中String與StringBuffer)
由於String是固定長的字符串對象,累加String對象時,並非在一個String對象中擴增,而是重新創建新的String對象,如Str5=Str1+Str2+Str3+Str4,這條語句執行過程中會產生多個垃圾對象,因爲對次作“+”操作時都必須創建新的String對象,但這些過渡對象對系統來說是沒有實際意義的,只會增加更多的垃圾。避免這種情況可以改用StringBuffer來累加字符串,因StringBuffer是可變長的,它在原有基礎上進行擴增,不會產生中間對象。
(5)能用基本類型如Int,Long,就不用Integer,Long對象
基本類型變量佔用的內存資源比相應對象佔用的少得多,如果沒有必要,最好使用基本變量。
(6)儘量少用靜態對象變量
靜態變量屬於全局變量,不會被GC回收,它們會一直佔用內存。
(7)分散對象創建或刪除的時間
集中在短時間內大量創建新對象,特別是大對象,會導致突然需要大量內存,JVM在面臨這種情況時,只能進行主GC,以回收內存或整合內存碎片,從而增加主GC的.頻率。集中刪除對象,道理也是一樣的。它使得突然出現了大量的垃圾對象,空閒空間必然減少,從而大大增加了下一次創建新對象時強制主GC的機會。
與finalize方法
⑴gc方法請求垃圾回收
使用()可以不管JVM使用的是哪一種垃圾回收的算法,都可以請求Java的垃圾回收。需要注意的是,調用()也僅僅是一個請求。JVM接受這個消息後,並不是立即做垃圾回收,而只是對幾個垃圾回收算法做了加權,使垃圾回收操作容易發生,或提早發生,或回收較多而已。
⑵finalize方法透視垃圾收集器的運行
在JVM垃圾收集器收集一個對象之前 ,一般要求程序調用適當的方法釋放資源,但在沒有明確釋放資源的情況下,Java提供了缺省機制來終止化該對象釋放資源,這個方法就是finalize()。它的原型爲:
protected void finalize() throws Throwable
在finalize()方法返回之後,對象消失,垃圾收集開始執行。原型中的throws Throwable表示它可以拋出任何類型的異常。
因此,當對象即將被銷燬時,有時需要做一些善後工作。可以把這些操作寫在finalize()方法裏。
java 代碼
protected void finalize()
{
// finalization code here
}
⑶代碼示例
java 代碼
class Garbage{
int index;
static int count;
Garbage() {
count++;
tln("object "+count+" construct");
setID(count);
}
void setID(int id) {
index=id;
}
protected void finalize() //重寫finalize方法
{
tln("object "+index+" is reclaimed");
}
public static void main(String[] args)
{
new Garbage();
new Garbage();
new Garbage();
new Garbage();
(); //請求運行垃圾收集器
}
}
相關文章
-
java垃圾回收算法講解
Java的堆是一個運行時數據區,類的實例(對象)從中分配空間。Java虛擬機(JVM)的堆中儲存着正在運行的應用程序所建立的所有對象,這些對象通過new、newarray、anewarray和multianewarray等指令建立,但是它們不需要程序代碼 -
Java虛擬機垃圾收集算法
Java虛擬機的內存區域中,程序計數器、虛擬機棧和本地方法棧三個區域是線程私有的,隨線程生而生,隨線程滅而滅;棧中的棧幀隨着方法的進入和退出而進行入棧和出棧操作,每個棧幀中分配多少內存基本上是在類結構確定下來時就 -
Java虛擬機垃圾收集算法簡介
一 標記-清除算法(Mark-Sweep)首先標記出所有需要回收的對象,標記完成後統一回收。主要缺點: 1. 標記和清除效率都很低 2. 產生大量不連續的內存碎片,導致後面分配大內存空間失敗二 複製算法將可用內存劃分爲大小相等的 -
java垃圾回收的方法是什麼
說到垃圾回收(Garbage Collection,GC),很多人就會自然而然地把它和Java聯繫起來。在Java中,程序員不需要去關心內存動態分配和垃圾回收的問題,這一切都交給了JVM來處理。顧名思義,垃圾回收就是釋放垃圾佔用的空間,那麼在Jav -
Java內存溢出的解決方法
一、內存溢出類型1、fMemoryError: PermGen spaceJVM管理兩種類型的內存,堆和非堆。堆是給開發人員用的上面說的就是,是在JVM啓動時創建;非堆是留給JVM自己用的,用來存放類的信息的。它和堆不同,運行期內GC不會釋放空 -
如何解決java內存泄漏
在Java中,內存泄漏就是存在一些被分配的對象,這些對象有下面兩個特點,首先,這些對象是可達的,即在有向圖中,存在通路可以與其相連;其次,這些對象是無用的,即程序以後不會再使用這些對象。假如對象滿足這兩個條件,這些對象就可 -
總結Java垃圾回收器的方法和原理
說到垃圾回收(Garbage Collection,GC),很多人就會自然而然地把它和Java聯繫起來。在Java中,程序員不需要去關心內存動態分配和垃圾回收的問題,這一切都交給了JVM來處理。顧名思義,垃圾回收就是釋放垃圾佔用的空間,那麼在Jav -
如何解決java內存泄漏的問題
在C++中,內存泄漏的範圍更大一些。有些對象被分配了內存空間,然後卻不可達,由於C++中沒有GC,這些內存將永遠收不回來。在Java中,這些不可達的對象都由GC負責回收,因此不需要考慮這部分的內存泄露。注重事項:1.最基本的建議是 -
Javascript 閉包引起IE內存泄露分析
Javascript 閉包引起IE內存泄露分析複製代碼 代碼如下:function fors(){obj_a = obj_b;obj_ = obj_a;}複製代碼 代碼如下:function fors(){obj_b = {};obj_ = obj_b;}上面是兩個個很顯示的循環引用,IE中產生了內存泄露 -
Java 語言與C語言中垃圾回收的不同方式
導語:垃圾回收是一種動態存儲管理技術,它自動地釋放不再被程序引用的對象,按照特定的垃圾回收算法來實現資源自動回收。下面就由小編爲大家介紹一下Java 語言與C語言中垃圾回收的不同方式,歡迎大家閱讀! 1 Java語言中