【JAVA記憶體回收】Java 記憶體回收機制
下面這個圖,很清楚地說明物件在new的時候是怎樣開闢記憶體空間的
其中物件new出來的,是棧記憶體,變數的開闢是堆記憶體
Java的一個重要優點就是通過垃圾收集器GC (Garbage Collection)自動管理記憶體的回收,程式設計師不需要通過呼叫函式來釋放記憶體。因此,很多程式設計師認為Java 不存在記憶體洩漏問題,或者認為即使有記憶體洩漏也不是程式的責任,而是GC 或JVM的問題。其實,這種想法是不正確的,因為Java 也存在記憶體洩漏,但它的表現與C++不同。如果正在開發的Java 程式碼要全天24 小時在伺服器上執行,則記憶體漏洞在此處的影響就比在配置實用程式中的影響要大得多,即使最小的漏洞也會導致JVM耗盡全部可用記憶體。另外,在很多嵌入式系統中,記憶體的總量非常有限。在相反的情況下,即便程式的生存期較短,如果存在分配大量臨時物件(或者若干吞噬大量記憶體的物件)的任何Java 程式碼,而且當不再需要這些物件時也沒有取消對它們的引用,則仍然可能達到記憶體極限。
Java 的記憶體管理就是物件的分配和釋放問題。分配記憶體的方式多種多樣,取決於該種語言的語法結構。但不論是哪一種語言的記憶體分配方式,最後都要返回所分配的記憶體塊的起始地址,即返回一個指標到記憶體塊的首地址。在Java 中所有物件都是在堆(Heap)中分配的,物件的建立通常都是採用new或者是反射的方式,但物件釋放卻有直接的手段,所以物件的回收都是由Java虛擬機器通過垃圾收集器去完成的。這種收支兩條線的方法確實簡化了程式設計師的工作,但同時也加重了JVM的工作,這也是Java 程式執行速度較慢的原因之一。因為,GC 為了能夠正確釋放物件,GC 必須監控每一個物件的執行狀態,包括物件的申請、引用、被引用、賦值等,GC 都需要進行監控。監視物件狀態是為了更加準確地、及時地釋放物件,而釋放物件的根本原則就是該物件不再被引用。
Java 使用有向圖的方式進行記憶體管理,可以消除引用迴圈的問題,例如有三個物件,相互引用,只要它們和根程序不可達,那麼GC 也是可以回收它們的。
在Java 語言中,判斷一塊記憶體空間是否符合垃圾收集器收集標準的標準只有兩個:
一個是給物件賦予了空值null,以下再沒有呼叫過,
另一個是給物件賦予了新值,即 重新分配了記憶體空間。