當須要排查各類內存溢出,內存泄漏問題時,當垃圾收集成爲系統達到更高併發量的瓶頸的時候,咱們須要對自動化的GC和內存分配實施必要的監控和調節。java
實際上,程序計數器,虛擬機棧和本地方法棧是線程隔離的,每個棧幀中分配的內存在類結構必定的狀況下是固定的(這裏不考慮JIT優化),所以,只有這幾個區域無需考慮內存分配及回收問題,由於方法結束或者線程結束時內存天然被回收了。算法
Java堆及方法區則不同,一個接口的多個實現類需求的內存不同,一個方法中多個分支須要的內存也不同,這部份內存的分配及回收都是動態的,GC關注的也是這部份內存。緩存
給對象添加一個引用計數器,每當有一個地方引用它,那麼計數器的值加1,引用失效計數器的值減1。任什麼時候刻計數器爲零的對象就是不可能被再度使用的。併發
主流的Java虛擬機中沒有使用這個方法來管理內存。主要是它很難解決對象之間的相互循環引用的問題。框架
class GCObject {
public Object instance = null;
}
public class GCDemo {
public static void main(String[] args) {
GCObject obj1 = new GCObject(); // 1
GCObject obj2 = new GCObject(); // 2
obj1.instance = obj2; // 3
obj2.instance = obj1; // 4
obj1 = null; // 5
obj2 = null; // 6
}
}
複製代碼
以上分爲6個步驟:高併發
至此,產生內存泄漏。優化
目前主流的虛擬機都是採用該算法。spa
能夠做爲GC Roots的對象:線程
上圖中的reference1,2,3都是GC Roots對象。雖然實例3,5相互引用(連通),可是GC Roots不可達,這就是GC要回收的垃圾對象。代理
在JDK 1.2以前,Java中引用的定義:若是reference類型的數據中存儲的值表明的是另外一塊內存的起始地址,就稱這塊內存表明一個引用。
可是這樣很難描述一些引用的「強弱」關係。由於在一些系統的緩存功能中,有一些內存的收集釋放須要更爲的合理化。因而,引用被分爲強引用,軟引用,弱引用,虛引用4種。
Object obj = new Object();
這類引用若是存在那麼GC永遠不會回收這部份內存。SoftReference
類。WeakReference
類。PhantomReference
。在可達性算法中不可達對象並不是必定被GC。對象被GC至少須要兩次標記過程,第一次是判斷是否有同GC Roots相鏈接的引用鏈,若是沒有那麼判斷是否有必要執行finalize()
。
若是有必要執行的話,那麼將該對象放置到F-Queue中,而後經過虛擬機建立的一個低優先級的Finalizer線程執行它。
若是在這個過程當中(指被標記須要執行finalize
方法到內存被回收這個時間段以內),對象和任意一個GC Roots相關聯,那麼對象將會逃逸。
HotSpot中的永久代。 廢棄常量以及無用的類。 重點關注無用的類:
一些大量使用反射,動態代理,CGLib技術的框架以及OSGi這類頻繁定義ClassLoader的場景須要虛擬機具有類卸載的功能,以保證永久代不會發生內存溢出。
歡迎關注:www.renrunyun.com