日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

Java内存泄露系列--内存泄露的原因及解决方案(大全)

發布時間:2024/3/26 java 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java内存泄露系列--内存泄露的原因及解决方案(大全) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

原文網址:Java內存泄露系列--內存泄露的原因及解決方案(大全)_IT利刃出鞘的博客-CSDN博客

簡介

簡介

? ? ? ? 本文介紹Java中內存泄露的一些原因與解決方案。

? ? ? ? 如果內存泄露的空間足夠大,就會導致內存溢出(OOM)。

內存泄露的原因

? ? ? ? 堆內存中一個對象不再使用時,垃圾回收器卻無法從內存中刪除他們,導致內存泄露。

內存泄露的影響

  • 長時間連續運行時性能嚴重下降;
  • 出現OOM導致應用崩潰;

內存泄露的檢測與分析

通常我們可以借助MAT、LeakCanary等工具來檢測應用程序是否存在內存泄漏。

1、MAT是一款強大的內存分析工具,功能繁多而復雜。
2、LeakCanary則是由Square開源的一款輕量級的第三方內存泄漏檢測工具,當檢測到程序中產生內存泄漏時,它將以最直觀的方式告訴我們哪里產生了內存泄漏和導致誰泄漏了而不能被回收。?

內存泄露的類型

主要有以下類型:

  • ThreadLocal
  • static字段
  • 未關閉的資源
  • 集合容器
  • 改變哈希值
  • 內部類持有外部類
  • finalize()方法
  • 常量字符串
  • ThreadLocal

    相關網址

    Java的ThreadLocal導致內存泄露----原因/解決方案_IT利刃出鞘的博客-CSDN博客

    簡介

    ? ? ? ? 使用ThreadLocal時,每個線程只要處于存貨狀態就可保留對其ThreadLocal變量副本的隱式調用,且將保留其自己的副本。使用不當,就會引起內存泄露。

    ? ? ? ? 一旦線程不在存在,ThreadLocals就應該被垃圾收集,而現在線程的創建都是使用線程池,線程池有線程重用的功能,因此線程就不會被垃圾回收器回收。所以使用到ThreadLocals來保留線程池中線程的變量副本時,ThreadLocals沒有顯示的刪除時,就會一直保留在內存中,不會被垃圾回收。

    解決方法

  • 不再使用ThreadLocal時,調用remove()方法,該方法刪除了此變量的當前線程值。
  • 不要使用ThreadLocal.set(null),它只是查找與當前線程關聯的Map并將鍵值對設置為當前線程為null。
  • static字段

    簡介

    ? ? ? ? 大量使用static字段會潛在的導致內存泄露,在Java中,靜態字段通常擁有與整個應用程序相匹配的生命周期。

    ? ? ? ? 示例:單例的靜態特性使得其生命周期和應用的生命周期一樣長,如果一個對象已經不再需要使用了,而單例對象還持有該對象的引用,就會使得該對象不能被正常回收,從而導致了內存泄漏。

    解決方法

  • 最大限度的減少靜態變量的使用;
  • 單例模式時,依賴于延遲加載對象而不是立即加載方式。
  • 未關閉的資源

    簡介

    ? ? ? ?對于使用了BroadcastReceiver,ContentObserver,File,Cursor,Stream,Bitmap等資源,應該在Activity銷毀時及時關閉或者注銷,否則這些資源將不會被回收,從而造成內存泄漏。

    解決方法

    調用它的close()函數將其關閉掉,然后再設置為null

    注意

  • 一般使用finally塊關閉資源;關閉資源的代碼,不應該有異常;
  • jdk1.7后,可以使用try-with-resource塊。
  • 集合容器

    簡介

    ? ? ? ? 我們通常把一些對象的引用加入到了集合容器(比如ArrayList)中,如果在不需要該對象時,沒有把對象的引用從集合中清理掉,這樣這個集合就會越來越大。

    ????????如果這個List是臨時的,那沒問題,List被回收后里邊的對象引用也就不會被持有了(對象不可達),對象引用也會被回收。如果這個List不是臨時的,那么就會導致內存占用越來越大。

    ? ? ? ? 如果這個集合是static的話,那情況就更嚴重了。如果這些容器為靜態的,那么它們的生命周期與程序一致,則容器中的對象在程序結束之前將不能被釋放,從而造成內存泄漏。簡單而言,長生命周期的對象持有短生命周期對象的引用,盡管短生命周期的對象不再使用,但是因為長生命周期對象持有它的引用而導致不能被回收。

    解決方法

  • 如果是static類型的集合,在退出程序之前,將集合里的東西clear,然后置為null,再退出程序。
  • 改變哈希值

    簡介

    ? ? ? ? 當一個對象被存儲進HashSet集合中以后,就不能修改這個對象中的那些參與計算哈希值的字段了,否則,對象修改后的哈希值與最初存儲進HashSet集合中時的哈希值就不同了。在這種情況下,即使在contains方法使用該對象的當前引用作為的參數去HashSet集合中檢索對象,也將返回找不到對象的結果,這也會導致無法從HashSet集合中單獨刪除當前對象,造成內存泄露

    解決方法?

  • 不要修改這個對象中的那些參與計算哈希值的字段
  • 內部類持有外部類

    相關網址

    Java的內部類持有外部類導致內存泄露--原因/解決方案_IT利刃出鞘的博客-CSDN博客

    簡介

    ? ? ? ? 若一個外部類的實例對象的方法返回了一個內部類的實例對象,這個內部類對象被長期引用了,即使那個外部類實例對象不再被使用,但由于內部類持有外部類的實例對象,這個外部類對象將不會被垃圾回收,這也會造成內存泄露。

    ? ? ? ??在Java中,非靜態內部類和匿名類內部類都會潛在持有它們所屬的外部類的引用,但是靜態內部類卻不會。

    解決辦法

  • 如果內部類不需要訪問外部類成員,考慮轉換為靜態內部類。
  • finalize()方法

    簡介

    重寫finalize()方法時,該類的對象不會立即被垃圾收集器收集,如果finalize()方法的代碼有問題,那么會潛在的引發OOM;

    解決辦法

  • 盡量避免重寫finalize();或者保證finalize方法沒問題
  • 常量字符串

    簡介

    ? ? ? ? 如果我們讀取一個很大的String對象,并調用了intern(),那么它將放到字符串池中,位于PermGen中,只要應用程序運行,該字符串就會保留,這就會占用內存,可能造成OOM。

    解決方法

    • 增加PermGen的大小,-XX:MaxPermSize=512m;
    • 升級Java版本,JDK1.7后字符串池轉移到了堆中。?

    其他網址

    8種JVM內存溢出(OOM)的原因和解決方法--掘金

    Java中的內存泄露問題 及解決方法_java_多多-CSDN博客
    徹底搞懂Java內存泄露 - 簡書
    java中內存泄露8種情況的總結_java_ratel的博客-CSDN博客

    總結

    以上是生活随笔為你收集整理的Java内存泄露系列--内存泄露的原因及解决方案(大全)的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。