突破程序員基本功的16課-4(引用,內存,垃圾回收及技巧)

 

第4課 Java的內存回收

Java引用的種類

Java對象是否回收的標準是:是否有引用變量引用該對象。java

當一個對象被建立以後,GC會實時的監控每個對象的狀態,包括對象的申請,引用,被引用,賦值等。當其再也不被引用時,就會被回收。數據庫

 

若是把Java的程序看作是一個有向圖,若是從運行的起點可以到達某個對象,那麼它就是可達狀態,不然就處於不可達狀態數組

eg:緩存

參見圖:性能

能夠看到「第三個節點」並無被任何其餘對象引用,它處於不可達狀態,GC會適時的回收它。ui

三種狀態:spa

爲了更好的管理對象的引用,Java從1.2開始提供了三個類SoftReference,PhantomReference,WeakReference,概括起來:對象

強引用生命週期

軟引用內存

弱引用

虛引用

JVM是不會回收強引用的對象,即便內存不足的時候,因此它是形成Java泄露的主要緣由。

Java的內存泄露

內存泄露是指系統分配了內存,可是有些無用的內存卻沒有被收回,致使內存耗損愈來愈大。

雖然JVM的垃圾回收機制能夠回收沒有被引用的內存,可是要考慮,這個「垃圾」的含義,對於程序來講是垃圾,由於再也不使用它們了,可是若是它們還被引用着,卻對JVM來講不是垃圾。

在ArrayList的remove方法源碼中:

elementData[--size] = null;

就是爲了讓垃圾回收器回收的,不然就會產生內存泄露—刪除了一個對象,可是該對象所佔據的空間並不會被釋放。

好比:

左圖能夠看出,ArrayList的長度爲4,當刪除最後一個元素的時候(即指向d的元素),若是沒有elementData[--size] = null,那麼它就形如右圖,第四個元素已經沒法被該ArrayList訪問了(由於刪除以後ArrayList的長度爲3了),可是它仍然指向「d」,即這塊內存沒有被釋放,gc也不會回收它,那麼隨着使用次數多了,內存損耗越來愈大,就形成了內存泄露。

垃圾回收機制

 

 

內存管理小技巧

1.儘可能只用直接量建立String(或者基礎類的包裝類),好比:

String str = 「hello」

而不要使用String str = new String(「hello」);

雖然二者都會被JVM的字符串緩衝池緩衝,可是後者str所引用的String對象在底層還包含了一個char[]數組,該數組依次存放了h,e,l,l,o

另外,在字符串緩衝池中的字符串不會被gc回收

2.使用StringBuffer和StringBuilder,這二者是可變的。當進行字符串運算時,直接使用String,將會產生大量的臨時字符串,下降性能。

3.儘早釋放無用對象的引用

好比:

若是在obj = null;以後程序就執行完畢的話,這句話就沒有必要書寫了,由於局部變量會隨着方法執行完畢而自行銷燬,可是若是它後面還須要執行其餘的耗時操做,那麼仍是及時的將其釋放。

4.儘可能少使用靜態變量

由於static變量的生命週期是和類同步的,因此在類不被卸載的狀況下,靜態變量也會一直存儲在內存中

5.不要在常常調用的方法,循環中建立java對象

這兩種狀況的特徵是這些代碼會被常常調用,若是常常建立對象,雖然對象的生命週期不長,可是系統會不斷的分配,回收內存,致使性能降低。

6.緩存常常使用的對象

好比數據庫鏈接池,一般有兩種方式:

1.  使用HashMap緩衝

2.  使用開源項目

7.儘可能不要使用finalize方法

8.考慮使用軟引用

相關文章
相關標籤/搜索