欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

一篇文章帶你搞定JAVA內(nèi)存泄漏

 更新時間:2021年07月14日 11:18:45   作者:香菜聊游戲  
今天小編就為大家分享一篇關(guān)于Java內(nèi)存泄漏問題處理方法經(jīng)驗總結(jié),小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧

1、什么是內(nèi)存泄漏

內(nèi)存泄漏是指無用對象(不再使用的對象)持續(xù)占有內(nèi)存或無用對象的內(nèi)存得不到及時釋放,從而造成內(nèi)存空間的浪費稱為內(nèi)存泄漏。隨著垃圾回收器活動的增加以及內(nèi)存占用的不斷增加,程序性能會逐漸表現(xiàn)出來下降,極端情況下,會引發(fā)OutOfMemoryError導(dǎo)致程序崩潰。

2、內(nèi)存泄漏的原因

JVM 虛擬機是使用引用計數(shù)法和可達(dá)性分析來判斷對象是否可回收,本質(zhì)是判斷一個對象是否還被引用,如果沒有引用則回收。在開發(fā)的過程中,由于代碼的實現(xiàn)不同就會出現(xiàn)很多種內(nèi)存泄漏問題,讓gc 系統(tǒng)誤以為此對象還在引用中,無法回收,造成內(nèi)存泄漏。

3、內(nèi)存泄漏有哪些情況

3.1 代碼中沒有及時釋放,導(dǎo)致內(nèi)存無法回收。

下面的代碼,因為是雙向鏈表,但是斷開的不夠徹底,prev節(jié)點依然引用這當(dāng)前正在使用的節(jié)點,導(dǎo)致無法回收

public class ListNode {
    int val;
    ListNode next;
    ListNode prev;
    ListNode() {
    }
    ListNode(int val) {
        this.val = val;
    }
    public ListNode(int val, ListNode next, ListNode prev) {
        this.val = val;
        this.next = next;
        this.prev = prev;
    }

    public static void main(String[] args) {
        ListNode curr = new ListNode(1);
        ListNode prev = new ListNode(2);
        ListNode next = new ListNode(3);
        curr.prev = prev;
        curr.next = next;
        curr.prev = null;
    }
}
    public static void main(String[] args) {
        ListNode curr = new ListNode(1);
        ListNode prev = new ListNode(2);
        ListNode next = new ListNode(3);
        curr.prev = prev;
        curr.next = next;
        curr.prev = null;
    }
}

3.2 資源未關(guān)閉造成的內(nèi)存泄漏

各種連接,如數(shù)據(jù)庫連接、網(wǎng)絡(luò)連接和IO連接等,文件讀寫等,可以使用 try-with-resources 讀取完文件,自動資源釋放

try (RandomAccessFile raf = new RandomAccessFile(filePath, "r");) {
        Image image = null;
while((image = parseImage(raf)) != null){
            imageList.add(image);
        }
        return imageList;
} catch(Exception e){
    log.error("parse file error, path: {},", path, e);
    return null;
}

3.3 全局緩存持有的對象不使用的時候沒有及時移除,導(dǎo)致一直在內(nèi)存中無法移除

3.4 靜態(tài)集合類

如HashMap、LinkedList等等。如果這些容器為靜態(tài)的,那么它們的生命周期與程序一致,則容器中的對象在程序結(jié)束之前將不能被釋放,從而造成內(nèi)存泄漏。生命周期長的對象持有短生命周期對象的引用,盡管短生命周期的對象不再使用,但是因為長生命周期對象持有它的引用而導(dǎo)致不能被回收。

3.5 堆外內(nèi)存無法回收

堆外內(nèi)存不受gc的管理,可能因為第三方的bug出現(xiàn)內(nèi)存泄漏

4、內(nèi)存泄漏的解決辦法

1.盡量減少使用靜態(tài)變量,或者使用完及時 賦值為 null。

2.明確內(nèi)存對象的有效作用域,盡量縮小對象的作用域,能用局部變量處理的不用成員變量,因為局部變量彈棧會自動回收;

3.減少長生命周期的對象持有短生命周期的引用;

4.使用StringBuilder和StringBuffer進(jìn)行字符串連接,Sting和StringBuilder以及StringBuffer等都可以代表字符串,其中String字符串代表的是不可變的字符串,后兩者表示可變的字符串。如果使用多個String對象進(jìn)行字符串連接運算,在運行時可能產(chǎn)生大量臨時字符串,這些字符串會保存在內(nèi)存中從而導(dǎo)致程序性能下降。

5.對于不需要使用的對象手動設(shè)置null值,不管GC何時會開始清理,我們都應(yīng)及時的將無用的對象標(biāo)記為可被清理的對象;

6.各種連接(數(shù)據(jù)庫連接,網(wǎng)絡(luò)連接,IO連接)操作,務(wù)必顯示調(diào)用close關(guān)閉。

5、內(nèi)存問題排查

沒有任何一個程序員想要出現(xiàn)這種問題,但是出現(xiàn)了問題也要解決,內(nèi)存泄漏的主要表象就是內(nèi)存不足,內(nèi)存告警之后如何判斷是否有內(nèi)存泄漏。

第一步 首先確認(rèn)邏輯問題

查看內(nèi)存中對象的數(shù)量和大小,判斷是否在合理的范圍,如果在合理的范圍內(nèi),增大內(nèi)存配置,調(diào)整內(nèi)存比例就可以了。

命令:

jmap -heap pid

圖片

第二步:分析gc是否正常執(zhí)行

命令:

jstat -gcutil <pid> 1000

圖片

S0 — Heap上的 Survivor space 0 區(qū)已使用空間的百分比    
S1 — Heap上的 Survivor space 1 區(qū)已使用空間的百分比    
E — Heap上的 Eden space 區(qū)已使用空間的百分比    
O   — Heap上的 Old space 區(qū)已使用空間的百分比    
P   — Perm space 區(qū)已使用空間的百分比
YGC — 從應(yīng)用程序啟動到采樣時發(fā)生 Young GC 的次數(shù)
YGCT– 從應(yīng)用程序啟動到采樣時 Young GC 所用的時間(單位秒)    
FGC — 從應(yīng)用程序啟動到采樣時發(fā)生 Full GC 的次數(shù)
FGCT– 從應(yīng)用程序啟動到采樣時 Full GC 所用的時間(單位秒)    
GCT — 從應(yīng)用程序啟動到采樣時用于垃圾回收的總時間(單位秒)
LGCC - 進(jìn)行GC的原因(低版本jdk可能沒有這一列)

從這里觀察gc是否異常,也可以根據(jù)這個進(jìn)行jvm內(nèi)存分配調(diào)優(yōu),來提高性能降低gc對性能的損耗

第三步 確認(rèn)下版本新增代碼的改動,盡快從代碼上找出問題。

第四步:開啟各種命令行和 導(dǎo)出 dump 各種工具分析

-XX:+HeapDumpOnOutOfMemoryError
-XX:OnError
-XX:+ShowMessageBoxOnError

推薦使用jprofile 進(jìn)行本地分析,可以不用記住那么多命令。

圖片

總結(jié):

現(xiàn)在的服務(wù)器內(nèi)存雖然很大,但是且用且珍惜,不要等到出現(xiàn)問題了才知道后果,在開發(fā)中規(guī)范自己代碼,用完的對象及時釋放,減少垃圾對象。出現(xiàn)問題了也不要慌,仔細(xì)分析代碼,一切都是有原因的。

本篇文章就到這里了,希望能給你帶來幫助,也希望您能多多關(guān)注腳本之家的更多內(nèi)容!

相關(guān)文章

  • java 讀取zip文件的兩種方式示例詳解

    java 讀取zip文件的兩種方式示例詳解

    ZIP(壓縮文件)是一種常見的文件格式,在Java中可以使用java.util.zip包提供的API來讀取和處理ZIP文件,本文將介紹如何使用Java讀取ZIP文件,并提供代碼示例,感興趣的朋友跟隨小編一起看看吧
    2024-07-07
  • MyBatis之關(guān)于動態(tài)SQL解讀

    MyBatis之關(guān)于動態(tài)SQL解讀

    這篇文章主要介紹了MyBatis之關(guān)于動態(tài)SQL解讀,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-06-06
  • java阿拉伯?dāng)?shù)字轉(zhuǎn)中文數(shù)字

    java阿拉伯?dāng)?shù)字轉(zhuǎn)中文數(shù)字

    這篇文章主要為大家詳細(xì)介紹了java實現(xiàn)阿拉伯?dāng)?shù)字轉(zhuǎn)換為中文數(shù)字,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-04-04
  • Java序列化原理詳解

    Java序列化原理詳解

    這篇文章主要介紹了Java序列化原理詳解,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價值,感興趣的小伙伴可以參考一下
    2022-06-06
  • 淺談Java中@Autowired和@Inject注解的區(qū)別和使用場景

    淺談Java中@Autowired和@Inject注解的區(qū)別和使用場景

    本文主要介紹了淺談Java中@Autowired和@Inject注解的區(qū)別和使用場景,@Autowired注解在依賴查找方式和注入方式上更加靈活,適用于Spring框架中的依賴注入,而@Inject注解在依賴查找方式上更加嚴(yán)格,適用于Java的依賴注入標(biāo)準(zhǔn),感興趣的可以了解一下
    2023-11-11
  • Java并發(fā)編程之volatile與JMM多線程內(nèi)存模型

    Java并發(fā)編程之volatile與JMM多線程內(nèi)存模型

    這篇文章主要介紹了Java并發(fā)volatile與JMM多線程內(nèi)存模型,本文通過實例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-05-05
  • Java基礎(chǔ)之extends用法詳解及簡單實例

    Java基礎(chǔ)之extends用法詳解及簡單實例

    這篇文章主要介紹了 Java基礎(chǔ)之extends用法詳解及簡單實例的相關(guān)資料,需要的朋友可以參考下
    2017-02-02
  • springboot?log4j2日志框架整合與使用過程解析

    springboot?log4j2日志框架整合與使用過程解析

    這篇文章主要介紹了springboot?log4j2日志框架整合與使用,包括引入maven依賴和添加配置文件log4j2-spring.xml的相關(guān)知識,需要的朋友可以參考下
    2022-05-05
  • java判斷字符串是否有逗號的方法

    java判斷字符串是否有逗號的方法

    下面小編就為大家?guī)硪黄猨ava判斷字符串是否有逗號的方法。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-11-11
  • Java獲得一個數(shù)組的指定長度排列組合算法示例

    Java獲得一個數(shù)組的指定長度排列組合算法示例

    這篇文章主要介紹了Java獲得一個數(shù)組的指定長度排列組合算法,結(jié)合實例形式分析了java排列組合相關(guān)數(shù)組遍歷、運算操作技巧,需要的朋友可以參考下
    2019-06-06

最新評論