成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

什么是內存泄漏?該如何檢測?又該如何解決?

存儲 存儲軟件
這個問題是我之前翻看面經的時候見到的。那位小姐姐把內存泄漏當成了內存溢出問題去解答的,結果當場掛掉了。為此總結一下,之前和一位老哥也討論過這個問題??梢姴还苁敲嬖囘€是工作這都是一個極為重要的點。

 [[385281]]

前言

這個問題是我之前翻看面經的時候見到的。那位小姐姐把內存泄漏當成了內存溢出問題去解答的,結果當場掛掉了。為此總結一下,之前和一位老哥也討論過這個問題。可見不管是面試還是工作這都是一個極為重要的點。

我也曾在面阿里的時候也遇到過原題,題目是寫出倆內存泄漏案例,然后問如何排查?如何解決?

本篇文章大體結構來自外國大佬baeldung;

一、介紹

1、什么是內存泄漏

java的優勢之一就是內置了垃圾回收器GC,它幫助我們實現了自動化內存管理。但是GC再好,也有老馬失前蹄的時候,它不能保證提供一個解決內存泄漏的萬無一失的解決方案。什么是內存泄漏?可以看看下面這張圖,

也就是一部分內存空間我明明已經使用了,卻沒有引用指向這部分空間。造成這片已經使用的空間無法處理的情況。

正規點的理解:動態開辟的空間,在使用完畢后未釋放,結果導致一直占據該內存單元。直到程序結束。

2、內存泄漏的危害

  • 長時間運行,程序變卡,性能嚴重下降
  • 程序莫名其妙掛掉
  • OutOfMemoryError錯誤
  • 亂七八糟的錯誤,還不易排查

反正內存泄漏不是好事。

二、內存泄漏原因

內存泄漏原因太多了。說不定就是某一行代碼不對就會出現這種情況,因此這里給出最常見的幾種。關鍵的還是如何找出哪個地方出現了內存泄漏,代碼好修改,錯誤不易查。

1、大量使用靜態變量

靜態變量的生命周期與程序一致。因此常駐內存。

  1. public class StaticTest { 
  2.     public static  List<Integer> list = new ArrayList<>(); 
  3.     public void populateList() { 
  4.         for (int i = 0; i < 10000000; i++) { 
  5.             list.add((int)Math.random()); 
  6.         } 
  7.         System.out.println("running......"); 
  8.     } 
  9.     public static void main(String[] args) { 
  10.       System.out.println("before......"); 
  11.         new StaticTest().populateList(); 
  12.         System.out.println("after......"); 
  13.     } 

現在可以使用jvisualvm運行一邊,看看內存效果。

  • 帶static關鍵字(使用靜態變量)

從上圖可以看到,堆內存從一開始的135M左右飆升了到了200M。直接占據了65M的內存。

  • 不使用static關鍵字(不使用靜態變量)

由于全局變量與程序周期不一致,因此不使用時,就會進行回收。此時內存最高150M。

總結:由于靜態變量與程序生命周期一致,因此對象常駐內存,造成內存泄漏

2、連接資源未關閉

每當建立一個連接,jvm就會為這么資源分配內存。比如數據庫連接、文件輸入輸出流、網絡連接等等。

  1. public class FileTest { 
  2.  public static void main(String[] args) throws IOException { 
  3.   File f=new File("G:\\nginx配套資料\\筆記資料.zip"); 
  4.   System.out.println(f.exists()); 
  5.         System.out.println(f.isDirectory()); 
  6.  } 

依然使用jvisualvm運行一邊,看看內存效果。

可以看出,在連接文件資源時,jvm會為本資源分配內存。

3、equals()和hashCode()方法使用不當

定義新類時,如果沒有重新equals()和hashCode()方法,也有可能會造成內存泄漏。主要原因是沒有這兩個方法時,很容易造成重復的數據添加??蠢樱?/p>

  1. public class User
  2.  public String name
  3.  public int age; 
  4.  public User(String nameint age) { 
  5.   this.name = name
  6.   this.age = age; 
  7.  } 
  8. public class EqualTest { 
  9.  public static void main(String[] args) { 
  10.   Map<UserInteger> map = new HashMap<>(); 
  11.      for(int i=0; i<100; i++) { 
  12.          map.put(new User("", 1), 1); 
  13.      } 
  14.         System.out.println(map.size() == 1);//輸出為false 
  15.  } 

然后運行一下,看看內存情況:

內存從150M一下子飆升到225M,可見飆升的厲害。輸出為false,說明user對象被重復添加了。我們知道像HashMap在添加新的對象時,會對其hashcode進行比較,如果一樣,那就不插入。如果一樣那就插入。此時說明這100個User其hashcode不同。

現在重寫這倆方法再運行一邊:

  1. public class User
  2.  public static String name
  3.  public User(String name) { 
  4.   this.name = name
  5.  } 
  6.     @Override 
  7.     public boolean equals(Object o) { 
  8.         if (o == this) return true
  9.         if (!(o instanceof User)) { 
  10.             return false
  11.         } 
  12.         User user = (User) o; 
  13.         return User.name.equals(name); 
  14.     } 
  15.     @Override 
  16.     public int hashCode() { 
  17.         return name.hashCode(); 
  18.     }  

在EqualTest類再測試一遍,首先看看內存變化:

上圖可以看到上升幅度沒那么大。而且輸出為true,這是肯定的,由于重寫了hashcode和equal,所以HashMap添加的肯定是同一個對象。

4、內部類持有外部類

這個場景和上面類似。

5、finalize方法

這個方法之前曾經專門花過文章寫過,這個問題很簡單??匆粡垐D

這就是整個過程。不過在這里我們主要看的是finalize方法對垃圾回收的影響,其實就是在第三步,也就是這個對象含有finalize,進入了隊列但一直沒有被調用的這段時間,會一直占用內存。造成內存泄漏。

6、ThreadLocal的錯誤使用

ThreadLocal主要用于創建本地線程變量,不合理的使用也有可能會造成內存泄漏。

上面這張圖詳細的揭示了ThreadLocal和Thread以及ThreadLocalMap三者的關系。

1、Thread中有一個map,就是ThreadLocalMap

2、ThreadLocalMap的key是ThreadLocal,值是我們自己設定的。

3、ThreadLocal是一個弱引用,當為null時,會被當成垃圾回收

4、重點來了,突然我們ThreadLocal是null了,也就是要被垃圾回收器回收了,但是此時我們的ThreadLocalMap生命周期和Thread的一樣,它不會回收,這時候就出現了一個現象。那就是ThreadLocalMap的key沒了,但是value還在,這就造成了內存泄漏。

解決辦法:使用完ThreadLocal后,執行remove操作,避免出現內存溢出情況。

現在介紹了幾種常見的內存泄漏情況,上面的知識點比較常見,最主要的是如何檢測出來。

三、檢測內存泄漏

檢測的目的是定位內存泄漏出現的位置,常見的有以下幾種方法:

1、工具分析

這個工具比較多,比如說JProfiler、YourKit、Java VisualVM和Netbeans Profiler。他可以幫助我們分析是哪一個對象或者是類內存的飆升。也可以看到內存CPU的等等各種情況。上面多次演示到了。

2、垃圾回收分析

這個其實也可以用工具進行分析。上面的VisualVM中,可以打印堆。也可以從外部導入dump文件進行分析。

如果不用工具的話,我們可以通過IDE看到。JVM配置添加-verbose:gc。然后就會打印出相關信息。下面這張圖非原創,來自Baeldung。

3、基準測試

也就是使用科學的方式進行分析java代碼的性能。進而判斷分析。

四、結論

內存泄漏是個很嚴重的問題,也比較常見。最主要的原因是動態開辟的空間,在使用完畢后未釋放,結果導致一直占據該內存單元。直到程序結束。因此良好的代碼規范,可以有效地避免這些錯誤。

本文轉載自微信公眾號「愚公要移山」,可以通過以下二維碼關注。轉載本文請聯系愚公要移山公眾號。

 

責任編輯:武曉燕 來源: 愚公要移山
相關推薦

2025-04-01 05:22:00

JavaThread變量

2024-10-24 16:51:08

2024-09-09 09:41:03

內存溢出golang開發者

2022-09-28 11:50:47

物聯網安全LOT

2025-04-25 08:25:00

DNS污染網絡攻擊IP地址

2018-11-14 12:18:35

設計畫面太亂視覺元素

2015-05-15 17:29:13

.Netxp系統如何解決

2022-09-07 07:05:25

跨域問題安全架構

2018-11-21 08:28:30

Docker業務容器

2021-10-18 22:29:54

OOMJava Out Of Memo

2023-02-15 07:03:41

跨域問題面試安全

2019-02-25 11:16:29

Windows 10錯誤distributed

2021-08-09 09:54:37

內存泄漏JS 阿里云

2021-08-05 15:28:22

JS內存泄漏

2024-01-30 10:12:00

Java內存泄漏

2019-06-24 19:00:09

JavaScript內存泄漏垃圾回收

2024-01-10 09:44:11

MySQL死鎖

2023-12-18 10:45:23

內存泄漏計算機服務器

2025-06-09 07:46:44

服務降級高并發

2013-12-17 15:46:04

iOS開發iOS 內存泄漏
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 亚洲最大av | 久久精品国产一区二区三区 | 九色在线观看 | 欧美日韩综合一区 | 成人久久视频 | 日本黄色不卡视频 | 韩日在线视频 | 久久精品亚洲成在人线av网址 | 九九久久精品 | 成人网在线观看 | 激情三区| 欧美lesbianxxxxhd视频社区 | 狠狠躁天天躁夜夜躁婷婷老牛影视 | 91香蕉视频在线观看 | 欧美成人a | 第四色播日韩第一页 | 国产成人精品免费 | 久在线观看 | 波多野吉衣在线播放 | 国产农村妇女精品一二区 | 免费观看一级黄色录像 | 国产电影一区二区在线观看 | 密色视频 | 色婷婷精品国产一区二区三区 | 国产69久久精品成人看动漫 | 亚洲高清av | 成人免费看黄网站在线观看 | 免费小视频在线观看 | 久久久妇女国产精品影视 | 欧美中文字幕一区 | 日韩一区二区三区av | 麻豆精品久久 | 黄色网址大全在线观看 | 色综网 | 国产成人免费 | 国产精品区二区三区日本 | 日本三级电影免费 | 日本在线视 | 成人av鲁丝片一区二区小说 | 天天艹逼网 | 日韩电影在线 |