1. 程式人生 > >java記憶體洩漏和記憶體溢位

java記憶體洩漏和記憶體溢位

java記憶體洩漏和記憶體溢位

  1. 概念
    a)記憶體洩露:被分配物件可達但無用
    b)記憶體溢位:無法申請到足夠的記憶體而產生的錯誤

  2. 記憶體洩漏場景
    a)建立和應用生命週期一樣的單例物件
    b)建立匿名內部類的靜態物件
    c)未關閉資源
    d)長時間存在的集合容器中建立生命週期短的物件

    示例:A a = new A();
         B b = new B(a);
         a = null;  //期望a被回收,但事實是b中還有a的引用,所以導致a記憶體地址不可用,導致洩漏。可以使用弱引用(當a失效時,所有的引用也失效)解決。
    

    e)修改hashset中的值,因此改變了該物件的雜湊值

  3. 記憶體溢位場景
    a)堆記憶體溢位
    b)方法區記憶體溢位(反射,靜態變數)
    c)執行緒棧溢位(遞迴)

  4. 分析記憶體溢位(mat分析記憶體工具
    通過引數 -XX:+HeapDumpOnOutOfMemoryError 可以讓虛擬機器在出現溢位時Dump出當前的記憶體堆轉儲快照以便事後進行分析。如果時採用的eclispse開發工具,自帶一個記憶體影像分析工具對dump 出來的堆轉儲快照進行分析,重點時分析到底時出現了記憶體洩漏(Memory Leak)還是 記憶體溢位(Memeory OverFlow).
    如果出現的記憶體洩露問題,進一步通過工具檢視洩露物件到GC Roots 的引用連。找到洩露物件時通過怎麼樣的路徑與GC Roots 相關聯並導致垃圾收集器無法自動回收他們的,掌握了洩露物件的型別資訊以及GCRoots 引用連的資訊,就可以比較準確的定位出洩露程式碼的位置。
    如果不存在洩露,換句話說就是 記憶體中的物件確實都必須存活著,那就檢查虛擬機器的堆引數,與機器實體記憶體對比看是否好可以調大,從程式碼上檢查是否存在某些物件生命週期過長,持有狀態時間過長的情況,嘗試減少程式執行期間的記憶體消耗。

  5. 避免記憶體溢位
    a)儘早釋放無用記憶體
    b)處理字串儘可能使用StringBuffer,因為每建立一個String佔一個獨立記憶體
    c)少用靜態變數(JDK1.8不存在方法區,不用考慮)
    d)避免迴圈中建立物件