自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

什么是內(nèi)存泄漏?該如何檢測(cè)?又該如何解決?

存儲(chǔ) 存儲(chǔ)軟件
這個(gè)問題是我之前翻看面經(jīng)的時(shí)候見到的。那位小姐姐把內(nèi)存泄漏當(dāng)成了內(nèi)存溢出問題去解答的,結(jié)果當(dāng)場(chǎng)掛掉了。為此總結(jié)一下,之前和一位老哥也討論過這個(gè)問題??梢姴还苁敲嬖囘€是工作這都是一個(gè)極為重要的點(diǎn)。

 [[385281]]

前言

這個(gè)問題是我之前翻看面經(jīng)的時(shí)候見到的。那位小姐姐把內(nèi)存泄漏當(dāng)成了內(nèi)存溢出問題去解答的,結(jié)果當(dāng)場(chǎng)掛掉了。為此總結(jié)一下,之前和一位老哥也討論過這個(gè)問題??梢姴还苁敲嬖囘€是工作這都是一個(gè)極為重要的點(diǎn)。

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

本篇文章大體結(jié)構(gòu)來(lái)自外國(guó)大佬baeldung;

一、介紹

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

java的優(yōu)勢(shì)之一就是內(nèi)置了垃圾回收器GC,它幫助我們實(shí)現(xiàn)了自動(dòng)化內(nèi)存管理。但是GC再好,也有老馬失前蹄的時(shí)候,它不能保證提供一個(gè)解決內(nèi)存泄漏的萬(wàn)無(wú)一失的解決方案。什么是內(nèi)存泄漏?可以看看下面這張圖,

也就是一部分內(nèi)存空間我明明已經(jīng)使用了,卻沒有引用指向這部分空間。造成這片已經(jīng)使用的空間無(wú)法處理的情況。

正規(guī)點(diǎn)的理解:動(dòng)態(tài)開辟的空間,在使用完畢后未釋放,結(jié)果導(dǎo)致一直占據(jù)該內(nèi)存單元。直到程序結(jié)束。

2、內(nèi)存泄漏的危害

  • 長(zhǎng)時(shí)間運(yùn)行,程序變卡,性能嚴(yán)重下降
  • 程序莫名其妙掛掉
  • OutOfMemoryError錯(cuò)誤
  • 亂七八糟的錯(cuò)誤,還不易排查

反正內(nèi)存泄漏不是好事。

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

內(nèi)存泄漏原因太多了。說不定就是某一行代碼不對(duì)就會(huì)出現(xiàn)這種情況,因此這里給出最常見的幾種。關(guān)鍵的還是如何找出哪個(gè)地方出現(xiàn)了內(nèi)存泄漏,代碼好修改,錯(cuò)誤不易查。

1、大量使用靜態(tài)變量

靜態(tài)變量的生命周期與程序一致。因此常駐內(nèi)存。

  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.     } 

現(xiàn)在可以使用jvisualvm運(yùn)行一邊,看看內(nèi)存效果。

  • 帶static關(guān)鍵字(使用靜態(tài)變量)

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

  • 不使用static關(guān)鍵字(不使用靜態(tài)變量)

由于全局變量與程序周期不一致,因此不使用時(shí),就會(huì)進(jìn)行回收。此時(shí)內(nèi)存最高150M。

總結(jié):由于靜態(tài)變量與程序生命周期一致,因此對(duì)象常駐內(nèi)存,造成內(nèi)存泄漏

2、連接資源未關(guān)閉

每當(dāng)建立一個(gè)連接,jvm就會(huì)為這么資源分配內(nèi)存。比如數(shù)據(jù)庫(kù)連接、文件輸入輸出流、網(wǎng)絡(luò)連接等等。

  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運(yùn)行一邊,看看內(nèi)存效果。

可以看出,在連接文件資源時(shí),jvm會(huì)為本資源分配內(nèi)存。

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

定義新類時(shí),如果沒有重新equals()和hashCode()方法,也有可能會(huì)造成內(nèi)存泄漏。主要原因是沒有這兩個(gè)方法時(shí),很容易造成重復(fù)的數(shù)據(jù)添加??蠢樱?/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.  } 

然后運(yùn)行一下,看看內(nèi)存情況:

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

現(xiàn)在重寫這倆方法再運(yùn)行一邊:

  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類再測(cè)試一遍,首先看看內(nèi)存變化:

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

4、內(nèi)部類持有外部類

這個(gè)場(chǎng)景和上面類似。

5、finalize方法

這個(gè)方法之前曾經(jīng)專門花過文章寫過,這個(gè)問題很簡(jiǎn)單。看一張圖

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

6、ThreadLocal的錯(cuò)誤使用

ThreadLocal主要用于創(chuàng)建本地線程變量,不合理的使用也有可能會(huì)造成內(nèi)存泄漏。

上面這張圖詳細(xì)的揭示了ThreadLocal和Thread以及ThreadLocalMap三者的關(guān)系。

1、Thread中有一個(gè)map,就是ThreadLocalMap

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

3、ThreadLocal是一個(gè)弱引用,當(dāng)為null時(shí),會(huì)被當(dāng)成垃圾回收

4、重點(diǎn)來(lái)了,突然我們ThreadLocal是null了,也就是要被垃圾回收器回收了,但是此時(shí)我們的ThreadLocalMap生命周期和Thread的一樣,它不會(huì)回收,這時(shí)候就出現(xiàn)了一個(gè)現(xiàn)象。那就是ThreadLocalMap的key沒了,但是value還在,這就造成了內(nèi)存泄漏。

解決辦法:使用完ThreadLocal后,執(zhí)行remove操作,避免出現(xiàn)內(nèi)存溢出情況。

現(xiàn)在介紹了幾種常見的內(nèi)存泄漏情況,上面的知識(shí)點(diǎn)比較常見,最主要的是如何檢測(cè)出來(lái)。

三、檢測(cè)內(nèi)存泄漏

檢測(cè)的目的是定位內(nèi)存泄漏出現(xiàn)的位置,常見的有以下幾種方法:

1、工具分析

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

2、垃圾回收分析

這個(gè)其實(shí)也可以用工具進(jìn)行分析。上面的VisualVM中,可以打印堆。也可以從外部導(dǎo)入dump文件進(jìn)行分析。

如果不用工具的話,我們可以通過IDE看到。JVM配置添加-verbose:gc。然后就會(huì)打印出相關(guān)信息。下面這張圖非原創(chuàng),來(lái)自Baeldung。

3、基準(zhǔn)測(cè)試

也就是使用科學(xué)的方式進(jìn)行分析java代碼的性能。進(jìn)而判斷分析。

四、結(jié)論

內(nèi)存泄漏是個(gè)很嚴(yán)重的問題,也比較常見。最主要的原因是動(dòng)態(tài)開辟的空間,在使用完畢后未釋放,結(jié)果導(dǎo)致一直占據(jù)該內(nèi)存單元。直到程序結(jié)束。因此良好的代碼規(guī)范,可以有效地避免這些錯(cuò)誤。

本文轉(zhuǎn)載自微信公眾號(hào)「愚公要移山」,可以通過以下二維碼關(guān)注。轉(zhuǎn)載本文請(qǐng)聯(lián)系愚公要移山公眾號(hào)。

 

責(zé)任編輯:武曉燕 來(lái)源: 愚公要移山
相關(guān)推薦

2024-10-24 16:51:08

2025-04-01 05:22:00

JavaThread變量

2024-09-09 09:41:03

內(nèi)存溢出golang開發(fā)者

2022-09-28 11:50:47

物聯(lián)網(wǎng)安全LOT

2025-04-25 08:25:00

DNS污染網(wǎng)絡(luò)攻擊IP地址

2018-11-14 12:18:35

設(shè)計(jì)畫面太亂視覺元素

2015-05-15 17:29:13

.Netxp系統(tǒng)如何解決

2018-11-21 08:28:30

Docker業(yè)務(wù)容器

2022-09-07 07:05:25

跨域問題安全架構(gòu)

2024-01-30 10:12:00

Java內(nèi)存泄漏

2021-10-18 22:29:54

OOMJava Out Of Memo

2019-06-24 19:00:09

JavaScript內(nèi)存泄漏垃圾回收

2021-08-09 09:54:37

內(nèi)存泄漏JS 阿里云

2021-08-05 15:28:22

JS內(nèi)存泄漏

2023-02-15 07:03:41

跨域問題面試安全

2023-12-18 10:45:23

內(nèi)存泄漏計(jì)算機(jī)服務(wù)器

2019-02-25 11:16:29

Windows 10錯(cuò)誤distributed

2015-07-10 09:15:47

LeakCanary內(nèi)存泄漏

2023-10-31 16:40:38

LeakCanary內(nèi)存泄漏

2018-12-07 10:52:08

內(nèi)存泄漏方法
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)