淺談Java–記憶體流失

來源:互聯網
上載者:User
  JAVA的記憶體回收機制,讓許多程式員覺得記憶體管理不是很重要,但是記憶體記憶體泄露的事情恰恰這樣的疏忽而發生,特別是對於Android開發,記憶體管理更為重要,養成良好的習慣,有利於避免記憶體的泄漏. 對象的幾種狀態:    這裡可以把許多個物件和引用看成是有向圖,頂點可以是對象也可以是引用,參考關聯性就是有向邊。
  1. 可達狀態:對象建立的時候,有引用指向它,這個時候在對象和引用之間建立了參考關聯性,即由引用發射有向邊指向對象,這個對象就是出於可達狀態
  2. 可恢複狀態:當引用不指向一個對象的時候,該對象就處於可恢複狀態,這時候在系統回收該對象之前,會調用finalize方法進行資源清理,如果調用這個方法後能重新讓引用變數去引用他,那麼他又恢複到可達狀態,不然會變成不可達狀態。
  3. 不可達狀態:當對象和引用變數失去了參考關聯性,並且調用了finalize方法後,不能恢複到可達狀態,那麼將永久性失去引用,此時系統才會真正去回收對象佔用的記憶體。
  何為記憶體流失:    記憶體流失就是程式運行中,java記憶體回收機制,會對一些不適用的記憶體進行回收,然後再重新分配,保證系統能再次用到這些記憶體,Java中所有不可達狀態都會被回收,但是一些處於可達狀態,但是程式卻再也不會用到的對象(佔著茅坑不拉屎),這些記憶體就無法被回收,他們對於程式員來說已經沒用,但是對於記憶體回收機制來說,他們是可達的,所以是“有用的”這些佔用的記憶體就會出現記憶體流失。  用一個棧的例子說明:
package CrazyJava;import javax.management.RuntimeErrorException;/** *  * @author ccf * */public class neicun {    /**     * @param args     */    class Stack {        private Object[] elementData;        private int size;        private int capacityIncrement;        public Stack(int initialCapacity) {            elementData = new Object[initialCapacity];        }        public Stack(int initialCapacity, int capacityIncrement) {            elementData = new Object[initialCapacity];            this.capacityIncrement = capacityIncrement;        }        public void push(Object object) {            ensureCapacity();            elementData[size++] = object;// 後加        }        public Object pop() {            if (size == 0)                throw new RuntimeException("空棧異常");            Object ele = elementData[--size];// 這裡為局部變數,當方法結束,局部變數會被回收            elementData[size] = null;// 消去強參考關聯性,避免產生內泄漏。            return ele;// 返回棧頂元素 size自減1個長度        }        public int size() {            return size;        }        private void ensureCapacity() {            // TODO Auto-generated method stub            // 數組已經滿了。進行擴容。            if (elementData.length == size) {                Object[] oldElmentata = elementData;                int newLength = 0;                if (capacityIncrement > 0) {                    newLength = elementData.length + capacityIncrement;                } else {                    newLength = (int) (elementData.length * 1.5);                }                elementData = new Object[newLength];                System.arraycopy(oldElmentata, 0, elementData, 0, size);            }        }    }    public static void main(String[] args) {        // TODO Auto-generated method stub        Stack stack = new neicun().new Stack(10);        for (int i = 0; i < 10; i++) {            stack.push("元素" + i);        }        for (int i = 0; i < 10; i++) {            System.out.println(stack.pop());        }    }}

  

  代碼中pop() 函數實現出棧,其中 elementData[size] = null;切斷了元素和其引用的參考關聯性,這樣可以使元素進入不可達狀態,從能被系統回收,如果不切斷引用,該元素將一直可以可達狀態,就會常駐記憶體。而針對上一句Object ele = elementData[--size];  就是為了暫存這個元素,用於作為return的傳回值,有人會問這個為什麼不會造成記憶體泄露,他們之間不是已經有了引用和被引用的關係,原因是這裡的Object對象是局部變數,局部變數的生命週期跟方法生命週期一樣,該方法結束了,搞局部變數會被記憶體回收機制收回,所以這個擔心是沒必要的。          從以上看來,記憶體流失可能性還是很大的,強參考型別(以後的博文會講)使我們用得最多的類型,這類引用只有再失去引用的時候才會被回收,其他情況都是不能被回收的,所以良好的編程習慣是避免記憶體流失的好辦法    怎樣避免記憶體流失:

    1. 盡量多使用直接量     
      例如String類型 
      String a =“ccf”  //採用直接量,JVM字串池會緩衝這個字串
      String b = new String(“ccf”); //但是直接調用構造方法的話,因為String內部是基於數組,所以會產生 字元數組儲存ccf三個字元。
    2. 多使用StringBuilder和StringBuffer
      使用StringBuilder和StringBuffer進行字串的操作,可以減少使用String進行字串操作產生的臨時字串
    3. 釋放無用的對象引用,就像上面棧的 pop ()方法
    4. 少用靜態變數,靜態變數生命週期跟類一樣,為類載入到類卸載這段時間,也就是知道程式結束。
    5. 避免在迴圈和經常調用的方法建立對象,因為這些情況會產生大量對象,特別是像for迴圈這些。
    6. 緩衝經常用到的對象,避免重複去建立相同對象,想android中Adapter中重寫getView就經常用到對象緩衝技術。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.