JVM學習-內存泄漏

內存泄漏的理解和分類

在這里插入圖片描述

  • 可達性分析算法來判斷對象是否是不再使用的對象,本質都是判斷一上對象是否還被引用,對于這種情況下,由于代碼的實現不同就會出現很多內存泄漏問題(讓JVM誤以為此對象還在引用,無法回收,造成內存泄漏)
內存泄漏(memory leak)
  • 嚴格來說,只有對象不會再被程序用到了,但是GC又不能回收他們的情況,叫內存泄漏
    在這里插入圖片描述
    • 對象X引用對象Y,X的生命周期比Y的生命周期長
    • 那么當Y生命周期結束的時候,X依然引用著Y,這時候,垃圾回收期是不會回收對象Y的
    • 如果對象X還引用著生命周期比較短的A,B,C,對象A對引用著對象a,b,c,這樣可能造成大量無用的對象不能被回收,進而占據了內存資源,造成內存泄漏,直到內存溢出
  • 申請了內存用完了不釋放,如一共有1024M內存,分配了512M的內存一直不回收,那么可用內存只有512M,仿佛泄露了一部分,通俗講內存泄漏就是【占著茅坑不拉shi】
內存溢出(out of memory)
  • 申請內存時,沒有足夠的內存可以使用
  • 通俗一點講,一個廁所三個坑,有兩個站著茅坑不走(內存泄漏),剩下一個坑,廁所一示接待壓力大,這時一下來了兩個人,坑位(內存)不夠了,內存泄漏變成內存溢出了
  • 內存泄漏和內存溢出的關系,內存泄漏增多,最終導致內存溢出
泄漏分類
  • 經常發生:發生內存泄露的代碼會被多次執行,每次執行,泄露一塊內存
  • 偶然發生:在某些特定情況下才會發生
  • 一次性:發生內存泄漏的方法只會執行一次
  • 隱式泄漏:一直占著內存不釋放,直到執行結束,嚴格的說這個不算內存泄漏,因為最終釋放掉了,但如果執行時間特別長,會導致內存耗盡
Java內存泄漏的8種情況
靜態集合類
  • 靜態集合類,如HashMap、LinkedList等,如果這些容器為靜態的,那么它們的生命周期與JVM程序一致,則容器中對象在程序結束這前將不能被釋放,從而造成內存泄漏,簡單而言,長生命周期的對象持有短生命周期對象的引用,盡管生命周期的對象不再使用,但是因為長生命周期對象持有它的引用而導致不能被回收。
public class MemoryLeak {static List list = new ArrayList();public void oomTests() {Object obj = new Object();   //局部變量,方法執行完成后不能被回收,因為被list所持有(list是靜態變量,生命周期同類)list.add(obj);}
}
單例模式
  • 單例模式和靜態集合導致內存泄漏的原因類似,因為單例的靜態特性,它的生命周期和JVM的生命周期一樣長,所以如果單例對象如果持有外部對象的引用,那么這個外部對象也不會被回收,那么就會造成內存泄漏。
內部類持有外部類
  • 內部類持有外部類,如果一個外部類的實例對象的方法返回一個內部類的實例對象
  • 這個內部類對象被長期引用了,即使那個外部類實例對象不再被使用,但由于內部類持有外部類的實例對象,這個外部類對象將不會被垃圾回收,這也會造成內存泄漏
各種連接,如數據庫連接,網絡連接和IO連接等
  • 各種連接,如數據庫連接,網絡連接和IO連接等
  • 在對數據庫進行操作的過程中,首先要建立與數據庫連接,當不再使用時,需要調用close方法來釋放與數據庫連接,只有連接被關閉后,垃圾回收器才會回收對應的對象
  • 否則,在訪問數據庫的過程中,對Connection,Statement或ResultSet不顯性地關閉,將會造成大量的對象無法被回收,從而引起內存泄漏
public static void main(String[] args) {try {Connection conn = null;Class.forName("com.mysql.jdbc.Driver");conn = DriverManager.getConnection("url","username","password");Statement stmt = conn.createStatement();ResultSet rs = stmt.executeQuery("....")} catch(Exception e) {  //異常日志}  finally {//①關閉結果集 Statement//②關閉聲明的對象 ResultSet//③關閉連接 Connection}
}
變量不合適作用域
  • 變量不合理的作用域,一般而言,一個變量的定義的作用范圍大于其使用范圍,很有可能會造成內存泄漏,另一方面,如果沒有及時地把對象設置為null,很有可能導致內存泄漏的定義
public class UsingRandom {private String msg;public void receiveMsg() {msg = readFromNet();  //從網絡中接收數據保存到msg中saveDB();       //將msg保存到數據庫中}
}
  • 上面偽代碼,通過readFromNet方法把接收到的消息保存到變量msg中,然后調用saveDB方法把msg內存保存到數據庫,此時msg已經沒用了,由于msg的生命周期與對象的生命周期相同,此時msg不能回收,因此造成內存泄漏
  • 實際msg變量可以放在receiveMsg方法內部 ,當方法用完,那么msg的生命周期就結束了,此時就可以回收了,另一種方法,使用完msg后,將msg=null,此時垃圾回收器也會回收msg內存空間
改變哈希值
  • 當一個對象被存儲進HashSet集合中后,就不能修改這個對象中的那些參與計算哈希值的字段了,否則,對象修改后的哈希值與最初存儲進HashSet集合中的哈希值就不同了,在這種情況下,即使用在contains方法使用該對象的當前引用作為的參數去HashSet集合中檢索對象,也將返回找不到對象的結果,這也會導致無法從HashSet集合中單獨刪除當前對象,造成內存泄漏
  • 這也是String設置成不可變類型的原因,可以放心把String存入HashSet,或把String當成HashMap的key值
  • 當我們需要把自定義的類保存到散列表時,需要保證對象的hashCode不可變
public class ChangeHashCode1 {public static void main(String[] args) {HashSet<Point> hs = new HashSet<>();Point cc = new Point();cc.setX(10);      //hashCode = 41hs.add(cc);cc.setX(20);      //hashCode = 51System.out.println("hs.remove = " + hs.remove(cc));   // falsehs.add(cc);System.out.println("hs.size = " + hs.size());         //2}
}
class Point {int x;public int getX() {return x;}public void setX(int x) {this.x = x;}@Overridepublic int hashCode() {final int prime = 31;int result = 1;result = prime * result + x;return result;}@Overridepublic boolean equals(Object obj) {if (this == obj) {return true;}if (obj == null) return false;if (getClass() != obj.getClass()) return false;Point other = (Point) obj;if (x != other.x) return false;return true;}
}
//執行結果
hs.remove = false
hs.size = 2
緩存泄漏
  • 一旦對象引用放入緩存中,很容易遺忘,比如,之前項目在一次上線的時候,應用啟動奇慢直至夯死,因為代碼中會加載一個表中的數據到緩存(內存)中,測試環境只有幾百條數據,但是生產環境有幾百萬的數據。
  • 對于這個問題,可以使用WeakHashMap代表緩存,此種Map的特點是,當除了自身有對key的引用外,此key沒有其他引用那么此map會自動丟棄此值。
public class MapTest {static Map wMap = new WeakHashMap();static Map map = new HashMap();public static void main(String[] args) {init();testWeakHashMap();testHashMap();}public static void init() {String ref1 = new String("object1");String ref2 = new String("object2");String ref3 = new String("object3");String ref4 = new String("object4");wMap.put(ref1,"cacheObject1");wMap.put(ref2,"cacheObject2");map.put(ref3,"cacheObject3");map.put(ref4,"cacheObject4");System.out.println("String引用ref1,ref2,ref3,ref4消失");}public static void testWeakHashMap(){System.out.println("WeakHashMap GC前");for (Object o : wMap.entrySet()) {System.out.println(o);}try {System.gc();TimeUnit.SECONDS.sleep(5);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("WeakHashMap GC后");for (Object o : wMap.entrySet()) {System.out.println(o);}}public static void testHashMap() {System.out.println("HashMap GC前");for (Object o : map.entrySet()) {System.out.println(o);}try {System.gc();TimeUnit.SECONDS.sleep(5);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("HashMap GC后");for (Object o : map.entrySet()) {System.out.println(o);}}
}
//執行結果
String引用ref1,ref2,ref3,ref4消失
WeakHashMap GC前
object2=cacheObject2
object1=cacheObject1
WeakHashMap GCHashMap GC前
object4=cacheObject4
object3=cacheObject3
HashMap GC后
object4=cacheObject4
object3=cacheObject3
監聽器和回調
  • 如果客戶端在你實現API注冊回調,卻沒有顯示的取消,就會產生積聚,需要確保回調被當作垃圾回收的最佳方法是只保存它的弱引用,保存成WeakHashMap的鍵

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/23044.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/23044.shtml
英文地址,請注明出處:http://en.pswp.cn/web/23044.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

旭日X3與英偉達Orin NX通過TCP傳輸圖片

觀前提醒&#xff1a;本文主要內容為使用Python在局域網內建立TCP連接并傳輸圖片信息&#xff0c;計算機為一塊旭日X3和一塊英偉達Orin NX。 一、什么是TCP TCP&#xff08;傳輸控制協議&#xff09;是一種可靠的、面向連接的協議&#xff0c;它確保數據包的順序傳輸和完整性…

關于教務排課的那些事

在辦學過程中&#xff0c;你是否被如下問題困擾&#xff1f; 1、排課功率低&#xff1a; 為了確保師資資源得到充分利用&#xff0c;教務教師排課要求了解每一個全職和兼職教師&#xff0c;了解每一個人的時刻組織和帶班狀況&#xff0c;因而在排課的時分需求處理很多的信息&a…

【Java數據結構】二叉樹詳解(四)

&#x1f512;文章目錄&#xff1a; 1.????前言~&#x1f973;&#x1f389;&#x1f389;&#x1f389; 2.給定一個二叉樹, 找到該樹中兩個指定節點的最近公共祖先 2.1第一種思路 2.2第二種思路 3.根據一棵樹的前序遍歷與中序遍歷構造二叉樹 4.根據一棵樹的中序…

vite相關配置

1、vite開發環境和生產環境的環境變量配置 1、環境變量配置 vite本身會直接讀取為什么會讀取&#xff0c;因為含有dotenv第三方庫 &#xff0c;會直接讀取 .env文件&#xff0c; 2、css模塊化簡單處理 css:{modules:{localsConvention: "camselCaseOnly" // 打包配…

機器學習_決策樹與隨機森林

決策樹是一種常用的監督學習算法&#xff0c;既可以用于分類任務也可以用于回歸任務。決策樹通過遞歸地將數據集劃分成更小的子集&#xff0c;逐步建立樹結構。每個節點對應一個特征&#xff0c;樹的葉子節點表示最終的預測結果。構建決策樹的關鍵是選擇最佳的特征來分割數據&a…

圖文型LED顯示屏的結構與安裝

隨著科技的不斷進步&#xff0c;LED顯示屏已成為商業廣告、公共信息顯示等領域不可或缺的一部分。圖文型LED顯示屏以其獨特的優勢和多樣化的應用場景&#xff0c;受到了市場的廣泛歡迎。本文將詳細介紹圖文型LED顯示屏的結構特點、工作原理以及安裝指南。 1、圖文型LED顯示屏的…

Python項目開發實戰:看圖猜成語小程序(案例教程)

一、項目背景與概述 在現代社會,隨著智能手機的普及和移動互聯網的快速發展,移動應用(App)已經成為人們日常生活中不可或缺的一部分。看圖猜成語作為一種集知識性和娛樂性于一體的游戲,深受大眾喜愛。本項目旨在開發一個基于Python的看圖猜成語小程序,讓用戶能夠通過簡單…

跨境電商|Facebook Marketplace怎么做?

2016 年&#xff0c;Facebook打造了同名平臺 Facebook Marketplace。通過利用 Facebook 現有的龐大客戶群&#xff0c;該平臺取得了立竿見影的成功&#xff0c;每月訪問量將超過 10 億。對于個人賣家和小企業來說&#xff0c;Facebook Marketplace是一個不錯的銷貨渠道&#xf…

Java內部類、枚舉類、注解類

Java 是一種面向對象的編程語言&#xff0c;它支持多種類型的類&#xff0c;包括內部類、枚舉類和注解類 一、內部類&#xff08;Inner Class&#xff09;&#xff1a; 內部類是定義在另一個類內部的類。它可以訪問外部類的成員&#xff08;包括私有成員&#xff09;&#xff…

AIGC在移動APP開發中的應用及未來前景

隨著科技的不斷進步&#xff0c;人工智能生成內容&#xff08;AIGC&#xff0c;Artificial Intelligence Generated Content&#xff09;在移動應用開發中的應用越來越廣泛。AIGC不僅能提高開發效率&#xff0c;還能帶來更好的用戶體驗。本文將探討AIGC在移動APP開發中的應用及…

通過ssr-echarts,服務端生成echarts圖

ssr-echarts &#xff1a;一個開源項目&#xff0c;它能夠服務端渲染 ECharts 圖表&#xff0c;并直接生成 PNG 圖片返回。該項目提供了多種主題&#xff0c;并且支持 GET 和 POST 請求。如果參數較多&#xff0c;建議使用 POST 方法。用戶可以自己部署這個服務。 1. 服務端安裝…

Three.js-實現加載圖片并旋轉

1.實現效果 2. 實現步驟 2.1創建場景 const scene new THREE.Scene(); 2.2添加相機 說明&#xff1a; fov&#xff08;視場角&#xff09;&#xff1a;視場角決定了相機的視野范圍&#xff0c;即相機可以看到的角度范圍。較大的視場角表示更廣闊的視野&#xff0c;但可能…

第 10 章 nodelet(自學二刷筆記)

重要參考&#xff1a; 課程鏈接:https://www.bilibili.com/video/BV1Ci4y1L7ZZ 講義鏈接:Introduction Autolabor-ROS機器人入門課程《ROS理論與實踐》零基礎教程 10.4 nodelet ROS通信是基于Node(節點)的&#xff0c;Node使用方便、易于擴展&#xff0c;可以滿足ROS中大多…

SBOM是如何幫助醫療器械制造商提高產品透明度的?

SBOM&#xff08;軟件物料清單&#xff09;通過以下方式幫助醫療器械制造商提高產品透明度&#xff1a; 1. 詳細記錄軟件組成 SBOM詳細列出了醫療器械所使用的所有軟件組件、版本、作者、許可證信息等。這使得制造商能夠清晰地了解產品的軟件組成&#xff0c;包括每個組件的來…

基于springboot實現民族婚紗預定系統項目【項目源碼+論文說明】

基于springboot實現民族婚紗預定系統的設計演示 摘要 現代經濟快節奏發展以及不斷完善升級的信息化技術&#xff0c;讓傳統數據信息的管理升級為軟件存儲&#xff0c;歸納&#xff0c;集中處理數據信息的管理方式。本民族婚紗預定系統就是在這樣的大環境下誕生&#xff0c;其可…

【Emgu CV教程】10.15、FillPoly()不規則形狀填充顏色

文章目錄 一、概念二、填充不規則圖形1.原始素材2.代碼3.運行結果 二、最大輪廓填充顏色1.原始素材2.代碼3.運行結果 一、概念 圖像的連通域是指圖像中具有相同像素值并且位置相鄰的像素組成的區域&#xff0c;連通域分析是指在圖像中尋找出彼此互相獨立的連通域并將其標記出來…

【最新鴻蒙應用開發】——Want信息載體

信息傳遞載體Want 1、概述 上一章節我們學習了UIAbility組件 【最新鴻蒙應用開發】——一篇搞懂什么是UIAbility-CSDN博客 &#xff0c;其中組件間的交互傳遞信息的媒介就是Want&#xff0c;本章節我們來更加深入學習Want的相關知識。 Want是一種對象&#xff0c;用于在應用組…

2. JavaScript 語法和數據類型

1. 基礎 JavaScript不區分大小寫 2. 注釋 // 單行注釋/* 這是一個更長的&#xff0c;多行注釋 *//* 然而&#xff0c;你不能&#xff0c;/* 嵌套注釋 */ 語法錯誤 */3. 聲明 var 聲明一個變量&#xff0c;可選初始化一個值。 let 聲明一個塊作用域的局部變量&#xff0c;可…

ORM(對象關系映射)概念詳解

一、技術難點 ORM&#xff0c;即對象關系映射&#xff08;Object-Relational Mapping&#xff09;&#xff0c;它的技術難點主要體現在如何將面向對象編程中的類和對象高效地映射到關系型數據庫中的表和記錄。具體來說&#xff0c;有以下幾個方面的技術挑戰&#xff1a; 數據類…

計算機畢業設計項目、管理系統、可視化大屏、大數據分析、協同過濾、推薦系統、SSM、SpringBoot、Spring、Mybatis、小程序項目編號1-500

大家好&#xff0c;我是DeBug&#xff0c;很高興你能來閱讀&#xff01;作為一名熱愛編程的程序員&#xff0c;我希望通過這些教學筆記與大家分享我的編程經驗和知識。在這里&#xff0c;我將會結合實際項目經驗&#xff0c;分享編程技巧、最佳實踐以及解決問題的方法。無論你是…