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

如何在您的Java應(yīng)用中查找并修復(fù)內(nèi)存泄漏

譯文
開發(fā) 后端 網(wǎng)站安全
您是否碰到過某個(gè)Java應(yīng)用程序起初運(yùn)行良好,經(jīng)過一段時(shí)間后卻緩慢下來了?或者它在處理少量文件時(shí)性能不錯(cuò),文件量一旦增加就性能下降的情況呢?如出現(xiàn)這樣的情況,很可能您遇到了內(nèi)存泄漏的問題。

【51CTO.com快譯】您是否碰到過某個(gè)Java應(yīng)用程序起初運(yùn)行良好,經(jīng)過一段時(shí)間后卻緩慢下來了?或者它在處理少量文件時(shí)性能不錯(cuò),文件量一旦增加就性能下降的情況呢?如出現(xiàn)這樣的情況,很可能您遇到了內(nèi)存泄漏的問題。

在應(yīng)對(duì)內(nèi)存泄漏時(shí),如果有人問我:“你是否知道此事的前因后果和應(yīng)對(duì)方法?”那么,我就會(huì)做出如下回答:

一、目標(biāo)受眾

盡管在一般情況下,本文中所介紹的方法是獨(dú)立于IDE和操作系統(tǒng)的,但是我在此所用到的截圖和說明仍然來自于Fedora Linux和帶插件開發(fā)的Eclipse。

二、內(nèi)存泄漏的癥狀

起初運(yùn)行速度快,但隨著時(shí)間的推移速度就慢下來了。比如說:

  • 能夠正常處理少量數(shù)據(jù)集,但應(yīng)對(duì)大量數(shù)據(jù)集時(shí)出現(xiàn)嚴(yán)重的性能問題。
  • 在您的JVM中,舊版本(Old-Generation)內(nèi)存的使用率持續(xù)增加。
  • 在您的JVM中,出現(xiàn)內(nèi)存耗盡的跳轉(zhuǎn)錯(cuò)誤。
  • 無故自我崩潰。

三、常見的內(nèi)存泄漏

Java中的內(nèi)存泄漏通常發(fā)生在您忘記關(guān)閉某個(gè)資源,或是某個(gè)對(duì)象的引用沒能釋放的時(shí)候。例如:

  • 文件/文本緩沖區(qū)沒被關(guān)閉。(請(qǐng)參見:https://git.eclipse.org/r/#/c/31313/中的案例)
  • 在equals()和hashcode()不被使用時(shí),各種哈希映射的引用仍然保持激活的狀態(tài),例如:
    1. import java.util.Map; 
    2. public class MemLeak { 
    3. public final String key; 
    4. public MemLeak(String key) { 
    5.     this.key = key; 
    6. public static void main(String args[]) { 
    7.     try { 
    8.       Map map = System.getProperties(); 
    9.       for(;;) { 
    10.          map.put(new MemLeak("key"), "value"); 
    11.       } 
    12.     } catch(Exception e) { 
    13.         e.printStackTrace(); 
    14.     } 
    15.   } 
  • 其他各種細(xì)節(jié)(請(qǐng)參見:https://www.toptal.com/java/hunting-memory-leaks-in-java#memleak)
  • 那些引用了各種外部類的內(nèi)部類所導(dǎo)致的泄漏。(可以將它們變成靜態(tài)來避免,請(qǐng)參見:https://blogs.oracle.com/olaf/entry/memory_leaks_made_easy)。

四、如何一次性修復(fù)它們?

這里提供兩種方法。第一種是嘗試“快速修復(fù)”。如果此法失敗,那么您就必須往下嘗試一條漫長的解決之路了。

  1. 快速修復(fù):使用Eclipse內(nèi)存泄漏的警告(去捕捉一些泄漏)。
  2. 手動(dòng)禁用和啟用您代碼的各個(gè)部分,并使用VisualVM(Jconsole或Thermostat)之類的工具觀察JVM的內(nèi)存使用情況。

1. 快速修復(fù):Eclipse內(nèi)存泄漏的警告/錯(cuò)誤。

為了遵從JDK 1.5+的代碼規(guī)范,Eclipse會(huì)向您“拋出”一些明顯泄漏用例的警告和錯(cuò)誤。更精確地說,任何使用了closable(如1.5后出現(xiàn)的outputStream)的對(duì)象,如果它的引用是被銷毀而不是封閉的話,就會(huì)拋出一個(gè)警告。然而在Eclipse的各個(gè)項(xiàng)目中,其檢漏功能并非總是被啟用的。因此,為了事先打開它們,您可以到項(xiàng)目的設(shè)置里,按照下圖所示進(jìn)行開啟:

快速修復(fù):Eclipse內(nèi)存泄漏的警告/錯(cuò)誤

此處Eclipse羅列出了各種內(nèi)存泄漏:

Eclipse羅列出了各種內(nèi)存泄漏

然而,就算使用了Eclipse的此項(xiàng)功能,系統(tǒng)仍無法探測(cè)到所有的文件關(guān)閉與泄漏。尤其是在使用舊式(1.5之前)代碼時(shí),您很可能會(huì)因?yàn)樗鼈冊(cè)谑褂眠^程中僅僅只是“關(guān)閉”(closable)了,而遇到泄漏問題了。也有時(shí)候,文件在深度嵌套中被打開/關(guān)閉,也會(huì)導(dǎo)致Eclipse無法檢測(cè)到。因此如果您碰到這種情況,就可能需要去嘗試第2種方法了。

2. 手動(dòng)禁用和啟用您代碼的各個(gè)部分,并使用VisualVM之類的工具觀察JVM的內(nèi)存使用情況。

如果您步入了這一步,那就不得不卷起袖子,做一些體力勞動(dòng)了。您需要通讀您的所有代碼,以試圖找出發(fā)生泄漏的地方。作為幫助,我建議您使用VisualVM之類的工具(當(dāng)然,Thermostat和MAT也是可行的)。

a. 配置的VisualVM

(1) 下載該工具。

(2) 打開終端,到達(dá)目錄.../visualvm_xyz/bin下,運(yùn)行shell腳本'./visualvm' (或在Windows上運(yùn)行visualvm.exe)。

(3) 您會(huì)看到彈出的主窗口。如果展開“本地”并雙擊您正在運(yùn)行的應(yīng)用(如下圖,我的應(yīng)用是一個(gè)子Eclipse),您就可以看到它的各種屬性。

(4) 在Fedora上用VisualVM進(jìn)行故障診斷:對(duì)我來說,最初我無法連接到自己的JVM,也不能夠使堆轉(zhuǎn)儲(chǔ)(heap-dumps)和分析(profiling)運(yùn)行起來。于是我探索出了如下步驟:

  • 確保用自己的登錄用戶身份運(yùn)行它,而不是使用sudo。
  • 對(duì)系統(tǒng)進(jìn)行全面更新(sudo yum update)。
  • 考慮重新啟動(dòng)是否有所幫助。
  • 嘗試在關(guān)閉所有正在運(yùn)行的Java應(yīng)用程序之后,再啟動(dòng)VisualVM。

(5) 添加一些插件。在使用VisualVM之前,我事先添加了一些插件。請(qǐng)點(diǎn)擊進(jìn)入工具->插件->“可用插件”。請(qǐng)選擇如下的插件(如果您喜歡,則可以隨意瀏覽并添加更多的插件):

  • 內(nèi)存池
  • 可視的GC
  • 終止應(yīng)用程序

b. 用VisualVM分析運(yùn)行的代碼

(1) 現(xiàn)在運(yùn)行您的Java應(yīng)用程序。

(2) 將VisualVM連接到您的應(yīng)用程序。

(3) 執(zhí)行那些容易導(dǎo)致性能變緩的操作。

(4) 檢查“監(jiān)控”和“內(nèi)存池”選項(xiàng)卡。如果您看到在“監(jiān)視器”選項(xiàng)卡中內(nèi)存顯示增加的話,那就按下“執(zhí)行GC”(垃圾收集),并監(jiān)視內(nèi)存的使用情況是否有所減少。

(5) 如果并不減少的話,那么就切換到“內(nèi)存池”選項(xiàng)卡,并檢查“Old Gen”(最開始的對(duì)象會(huì)停留在“Eden”中,然后通過Survivor空間進(jìn)行過渡,比較舊的對(duì)象會(huì)被移到“Old Gen”池中。如果出現(xiàn)泄漏,則會(huì)出現(xiàn)在Old-Gen池里。)。

(6) 現(xiàn)在返回去,并注釋掉程序代碼的大部分,從而定位到應(yīng)用程序開始變慢的位置。

(7) 重復(fù)上述過程,直到應(yīng)用程序完全不再有泄漏的發(fā)生。

(8) 然后,經(jīng)過反復(fù)迭代來重新啟用代碼的各個(gè)部分,并檢查VisualVM的內(nèi)存使用情況。一旦您的應(yīng)用程序再次開始泄漏,則馬上進(jìn)入導(dǎo)致內(nèi)存泄漏的該函數(shù)方法,從而進(jìn)一步縮小代碼的考察范圍。

(9) 最終,您將能夠把問題縮小到具體某一個(gè)類,甚至某一個(gè)單一的方法上。請(qǐng)仔細(xì)驗(yàn)證所有文件的緩沖區(qū)是否已被關(guān)閉,而HashMap是否被正確的使用了。

五、標(biāo)準(zhǔn)化您的代碼

有時(shí)候會(huì)很難確定您那“金光閃閃”的新代碼是否真的會(huì)比舊代碼更好。面對(duì)這種情況下,您需要去標(biāo)準(zhǔn)化應(yīng)用程序的性能。您可以將下面的這段代碼插入到任何您認(rèn)為適當(dāng)?shù)奈恢茫垣@取有關(guān)運(yùn)行時(shí)間和垃圾收集次數(shù)的相關(guān)信息:

  1. long start = System.currentTimeMillis(); 
  2. .. 
  3.  //your code 
  4. .. 
  5. long end = System.currentTimeMillis(); 
  6. System.out.println("Run time: " + Long.toString(end - start)); 
  7. System.out.println(printGCStats()); 
  8. public static String printGCStats() { 
  9.  long totalGarbageCollections = 0
  10.  long garbageCollectionTime = 0
  11.  for (GarbageCollectorMXBean gc : ManagementFactory.getGarbageCollectorMXBeans()) { 
  12.  long count = gc.getCollectionCount(); 
  13.  if (count >= 0) { 
  14.  totalGarbageCollections += count; 
  15.  } 
  16.  long time = gc.getCollectionTime(); 
  17.  if (time >= 0) { 
  18.  garbageCollectionTime += time; 
  19.  } 
  20.  } 
  21.  return "Garbage Collections: " + totalGarbageCollections + "n" + 
  22.  "Garbage Collection Time (ms): " + garbageCollectionTime; 

特別提醒一下:如果您是在主Eclipse中進(jìn)行測(cè)試的話,我建議去測(cè)試一個(gè)“干凈”的子Eclipse;或者是在您的Eclipse的一些“干凈”實(shí)例中進(jìn)行。因?yàn)檫@樣的話,其他各種插件是不會(huì)對(duì)標(biāo)準(zhǔn)的耗時(shí)產(chǎn)生影響的。

六、附加說明:堆轉(zhuǎn)儲(chǔ)

我個(gè)人使用的并不多,但有些人比較熱衷于“堆轉(zhuǎn)儲(chǔ)”。您可以在任何時(shí)候采取堆轉(zhuǎn)儲(chǔ),然后查看有多少類的實(shí)例被打開,以及它們使用了多大的空間。您可以通過雙擊它們來查看具體的內(nèi)容。如果您想獲悉自己的應(yīng)用程序產(chǎn)生了多少個(gè)對(duì)象的話,這種方法會(huì)非常有用。

堆轉(zhuǎn)儲(chǔ)

七、我的應(yīng)用并沒有泄漏,可為何還是很慢?

當(dāng)然也存在著一種可能性:就算您的代碼中并沒有任何的泄漏,它仍然運(yùn)行緩慢。如果出現(xiàn)這種情況的話,您就必須進(jìn)行代碼分析了。不過,代碼分析已經(jīng)超出了本文所涉及的范圍。這里推薦一個(gè)很好的YouTube視頻,它講解了如何去使用免費(fèi)和付費(fèi)的分析器來對(duì)Eclipse進(jìn)行分析,請(qǐng)參見:https://www.youtube.com/watch?v=YCC-CpTE2LU。

八、還能看哪些?

至此您可以潛下心來,花上一到兩天的時(shí)間去修復(fù)您的內(nèi)存泄漏問題了。在此過程中,如果您仍碰到麻煩的話,請(qǐng)參考如下的鏈接:

  • 捕捉內(nèi)存泄漏:https://www.toptal.com/java/hunting-memory-leaks-in-java
  • 內(nèi)部類的內(nèi)存泄漏問題:https://blogs.oracle.com/olaf/entry/memory_leaks_made_easy
  • 瀏覽Oracle的JVM GC指南:www.oracle.com/technetwork/java/javase/gc-tuning-6-140523.html

原標(biāo)題:How to Find and Fix Memory Leaks in Your Java Application,作者: Leo Ufimtsev

【51CTO譯稿,合作站點(diǎn)轉(zhuǎn)載請(qǐng)注明原文譯者和出處為51CTO.com】

責(zé)任編輯:趙寧寧 來源: 51CTO.com
相關(guān)推薦

2023-12-18 10:45:23

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

2024-12-05 08:58:47

2024-01-30 10:12:00

Java內(nèi)存泄漏

2022-05-26 09:51:50

JavaScrip內(nèi)存泄漏

2018-05-30 14:29:14

WindowsWindows 10系統(tǒng)文件

2023-01-31 16:54:47

Linux端口

2024-11-29 08:20:23

Rust內(nèi)存泄漏

2025-05-06 07:24:24

2019-12-06 10:05:28

Windows 10手機(jī)應(yīng)用程序

2012-08-13 10:14:36

IBMdW

2020-01-03 16:04:10

Node.js內(nèi)存泄漏

2019-10-29 09:10:57

Windows 10照片應(yīng)用標(biāo)記人物

2018-08-30 10:00:12

Windows 10修復(fù)黑屏

2019-01-30 18:24:14

Java內(nèi)存泄漏編程語言

2010-10-28 09:21:42

oracle中存圖片

2017-11-09 16:07:00

Web應(yīng)用內(nèi)存

2025-06-03 01:55:00

2018-08-23 10:50:08

Windows 10Windows隱私

2021-08-09 09:54:37

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

2021-08-05 15:28:22

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

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

主站蜘蛛池模板: 久久一区二区三区四区 | 人人色视频 | 日韩免费网站 | 中文字幕精品视频 | 久久久久久天堂 | 欧美亚洲在线视频 | 久久91| 成人在线精品 | 久久99精品久久久 | 久热精品在线 | 午夜在线 | 欧美成人手机在线 | 国产精品亚洲综合 | 国产天天操 | 日韩一区二区在线视频 | 一区二区三区电影网 | 久热精品在线播放 | 久久美国 | 国产高清精品一区二区三区 | 男人的天堂avav | 久草在线影 | h片在线观看网站 | 日韩视频成人 | 中文字幕亚洲视频 | 欧美日韩亚洲一区二区 | 日韩精品在线观看一区二区三区 | 操操日 | 综合在线视频 | 欧美性大战久久久久久久蜜臀 | 九九精品在线 | 精品国产乱码久久久久久a丨 | 日韩精品一区二区三区在线播放 | 久久精品一区 | 精品国产欧美 | 国产精品一区二区视频 | 国产精品久久 | 91成人 | 午夜精品在线观看 | 99免费在线观看视频 | 在线91| 久久久精品影院 |