若是本文幫助到你,本人不勝榮幸,若是浪費了你的時間,本人深感抱歉。 但願用最簡單的大白話來幫助那些像我同樣的人。若是有什麼錯誤,請必定指出,以避免誤導你們、也誤導我。 本文來自:www.jianshu.com/users/320f9… 感謝您的關注。html
Java的內存是不用咱們開發者本身來管理的,這個你們都知道,可是那它究竟是怎麼運做的呢? 咱們都知道GC,也就是垃圾回收機制,但到底什麼是GC。 咱們一塊兒來看看。java
垃圾回收是一種自動的存儲管理機制。當一些被佔用的內存再也不須要時,就應該予以釋放,以讓出空間,這種存儲資源管理,稱爲垃圾回收(garbage collection)。垃圾回收器可讓程序員減輕許多負擔,也減小程序員犯錯的機會。 咱們來主要看看Java的gc機制。程序員
整個Java堆能夠切割成爲三個部分:算法
在開始學習GC以前你應該知道一個詞:stop-the-world。無論選擇哪一種GC算法,stop-the-world都是不可避免的。 也就是說,當垃圾回收開始清理資源時,其他的全部線程都會被中止。因此,咱們要作的就是儘量的讓它執行的時間變短。若是清理的時間過長,在咱們的應用程序中就能感受到明顯的卡頓。數組
由於它對系統影響很明顯,因此它到底在何時執行呢?緩存
總的來講,有兩個條件會觸發主GC:性能優化
因爲是否進行主GC由JVM根據系統環境決定,而系統環境在不斷的變化當中,因此主GC的運行具備不肯定性,沒法預計它什麼時候必然出現,但能夠肯定的是對一個長期運行的應用來講,其主GC是反覆進行的。數據結構
以前已經瞭解到Java堆被主要分紅三個部分,而垃圾回收主要是在Young(年輕代)和Tenured(老年代)工做。 而 年輕代 又包括 Eden(伊利園)和兩個Survivor(倖存者)。 下面咱們就來看看這些空間是如何進行交互的:函數
一、首先,全部新生成的對象都是放在年輕代的Eden分區的,初始狀態下兩個Survivor分區都是空的。年輕代的目標就是儘量快速的收集掉那些生命週期短的對象。性能
二、當Eden區滿的的時候,小垃圾收集就會被觸發。
三、當Eden分區進行清理的時候,會把引用對象移動到第一個Survivor分區,無引用的對象刪除。
四、在下一個小垃圾收集的時候,在Eden分區中會發生一樣的事情:無引用的對象被刪除,引用對象被移動到另一個Survivor分區(S1)。此外,從上次小垃圾收集過程當中第一個Survivor分區(S0)移動過來的對象年齡增長,而後被移動到S1。當全部的倖存對象移動到S1之後,S0和Eden區都會被清理。注意到,此時的Survivor分區存儲有不一樣年齡的對象。
五、在下一個小垃圾收集,一樣的過程反覆進行。然而,此時Survivor分區的角色發生了互換,引用對象被移動到S0,倖存對象年齡增大。Eden和S1被清理。
六、這幅圖展現了從年輕代到老年代的提高。當進行一個小垃圾收集以後,若是此時年老對象此時到達了某一個個年齡閾值(例子中使用的是8),JVM會把他們從年輕代提高到老年代。
七、隨着小垃圾收集的持續進行,對象將會被持續提高到老年代。
八、這樣幾乎涵蓋了年輕一代的整個過程。最終,在老年代將會進行大垃圾收集,這種收集方式會清理-壓縮老年代空間。
參數 | 描述 |
---|---|
-Xms | JVM啓動的時候設置初始堆的大小 |
-Xmx | 設置最大堆的大小 |
-Xmn | 設置年輕代的大小 |
-XX:PermSize | 設置持久代的初始的大小 |
-XX:MaxPermSize | 設置持久代的最大值 |
根據GC的工做原理,咱們能夠經過一些技巧和方式,讓GC運行更加有效率
清除 將引用對象的 referent 域設置爲 null ,並將引用類在堆中引用的對象聲明爲 可結束的。 StrongReference 強引用:正常的對象,一直不會清理,直到爆炸。 SoftReference 軟引用:內存不夠的時候,遇到了就清了。 WeakReference 弱引用:只要遇到了就清了,注意:可能清了好幾回,都沒遇到。 PhantomReference 虛引用:虛顧名思義就是沒有的意思,創建虛引用以後經過get方法返回結果始終爲null。
PhantomReference 必須與 ReferenceQueue 類一塊兒使用。須要 ReferenceQueue 是由於它可以充當通知機制。當垃圾收集器肯定了某個對象是虛可及對象時, PhantomReference 對象就被放在它的 ReferenceQueue 上。將 PhantomReference 對象放在 ReferenceQueue 上也就是一個通知,代表 PhantomReference 對象引用的對象已經結束,可供收集了。這使您可以恰好在對象佔用的內存被回收以前採起行動。
給個軟引用的例子:
//首先定義一個HashMap,保存軟引用對象。
private Map<String, SoftReference<Bitmap>> imageCache = new HashMap<String, SoftReference<Bitmap>>();
//再來定義一個方法,保存Bitmap的軟引用到HashMap。
public void addBitmapToCache(String path) {
// 強引用的Bitmap對象
Bitmap bitmap = BitmapFactory.decodeFile(path);
// 軟引用的Bitmap對象
SoftReference<Bitmap> softBitmap = new SoftReference<Bitmap>(bitmap);
// 添加該對象到Map中使其緩存
imageCache.put(path, softBitmap);
}
//獲取的時候,能夠經過SoftReference的get()方法獲得Bitmap對象。
public Bitmap getBitmapByPath(String path) {
// 從緩存中取軟引用的Bitmap對象
SoftReference<Bitmap> softBitmap = imageCache.get(path);
// 判斷是否存在軟引用
if (softBitmap == null) {
return null;
}
// 取出Bitmap對象,若是因爲內存不足Bitmap被回收,將取得空
Bitmap bitmap = softBitmap.get();
return bitmap;
}
複製代碼
參考及學習連接:
www.cnblogs.com/shudonghe/p… Java 垃圾回收機制技術詳解 blog.csdn.net/lu100528736… Java 垃圾回收機制 (GC) 詳解、意義、建議 blog.csdn.net/ithomer/art… Java 內存模型及GC原理 www.codeceo.com/article/jav… Java GC專家系列1:理解Java垃圾回收 www.codeceo.com/article/jav… Java GC專家系列2:Java 垃圾回收的監控 www.codeceo.com/article/jav… Java GC 專家系列3:GC調優實踐
blog.csdn.net/huoyin/arti… Java中三個引用類SoftReference 、 WeakReference 和 PhantomReference的區別