真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

Java中怎么用弱引用堵住內(nèi)存泄漏

本篇內(nèi)容主要講解“Java中怎么用弱引用堵住內(nèi)存泄漏”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學(xué)習(xí)“Java中怎么用弱引用堵住內(nèi)存泄漏”吧!

創(chuàng)新互聯(lián)是專業(yè)的翁牛特網(wǎng)站建設(shè)公司,翁牛特接單;提供網(wǎng)站設(shè)計、成都網(wǎng)站制作,網(wǎng)頁設(shè)計,網(wǎng)站設(shè)計,建網(wǎng)站,PHP網(wǎng)站建設(shè)等專業(yè)做網(wǎng)站服務(wù);采用PHP框架,可快速的進行翁牛特網(wǎng)站開發(fā)網(wǎng)頁制作和功能擴展;專業(yè)做搜索引擎喜愛的網(wǎng)站,專業(yè)的做網(wǎng)站團隊,希望更多企業(yè)前來合作!

雖然用 Java? 語言編寫的程序在理論上是不會出現(xiàn)“內(nèi)存泄漏”的,但是有時對象在不再作為程序的邏輯狀態(tài)的一部分之后仍然不被垃圾收集。本月,負責(zé)保障應(yīng)用程序健康的工程師 Brian Goetz 探討了無意識的對象保留的常見原因,并展示了如何用弱引用堵住泄漏。
要讓垃圾收集(GC)回收程序不再使用的對象,對象的邏輯 生命周期(應(yīng)用程序使用它的時間)和對該對象擁有的引用的實際 生命周期必須是相同的。在大多數(shù)時候,好的軟件工程技術(shù)保證這是自動實現(xiàn)的,不用我們對對象生命周期問題花費過多心思。但是偶爾我們會創(chuàng)建一個引用,它在內(nèi)存中包含對象的時間比我們預(yù)期的要長得多,這種情況稱為無意識的對象保留(unintentional object retention)。

全局 Map 造成的內(nèi)存泄漏

無意識對象保留最常見的原因是使用 Map 將元數(shù)據(jù)與臨時對象(transient object)相關(guān)聯(lián)。假定一個對象具有中等生命周期,比分配它的那個方法調(diào)用的生命周期長,但是比應(yīng)用程序的生命周期短,如客戶機的套接字連接。需要將一些元數(shù)據(jù)與這個套接字關(guān)聯(lián),如生成連接的用戶的標識。在創(chuàng)建 Socket 時是不知道這些信息的,并且不能將數(shù)據(jù)添加到 Socket 對象上,因為不能控制 Socket 類或者它的子類。這時,典型的方法就是在一個全局 Map 中存儲這些信息,如清單 1 中的 SocketManager 類所示:

清單 1. 使用一個全局 Map 將元數(shù)據(jù)關(guān)聯(lián)到一個對象

public class SocketManager {
private Map

m = new HashMap();

public void setUser(Socket s, User u) {
m.put(s, u);
}
public User getUser(Socket s) {
return m.get(s);
}
public void removeUser(Socket s) {
m.remove(s);
}
}

SocketManager socketManager;
...
socketManager.setUser(socket, user);

這種方法的問題是元數(shù)據(jù)的生命周期需要與套接字的生命周期掛鉤,但是除非準確地知道什么時候程序不再需要這個套接字,并記住從 Map 中刪除相應(yīng)的映射,否則,Socket 和 User 對象將會永遠留在 Map 中,遠遠超過響應(yīng)了請求和關(guān)閉套接字的時間。這會阻止 Socket 和 User 對象被垃圾收集,即使應(yīng)用程序不會再使用它們。這些對象留下來不受控制,很容易造成程序在長時間運行后內(nèi)存爆滿。除了最簡單的情況,在幾乎所有情況下找出什么時候 Socket 不再被程序使用是一件很煩人和容易出錯的任務(wù),需要人工對內(nèi)存進行管理。

找出內(nèi)存泄漏

程序有內(nèi)存泄漏的第一個跡象通常是它拋出一個 OutOfMemoryError,或者因為頻繁的垃圾收集而表現(xiàn)出糟糕的性能。幸運的是,垃圾收集可以提供能夠用來診斷內(nèi)存泄漏的大量信息。如果以 -verbose:gc 或者 -Xloggc 選項調(diào)用 JVM,那么每次 GC 運行時在控制臺上或者日志文件中會打印出一個診斷信息,包括它所花費的時間、當(dāng)前堆使用情況以及恢復(fù)了多少內(nèi)存。記錄 GC 使用情況并不具有干擾性,因此如果需要分析內(nèi)存問題或者調(diào)優(yōu)垃圾收集器,在生產(chǎn)環(huán)境中默認啟用 GC 日志是值得的。

有工具可以利用 GC 日志輸出并以圖形方式將它顯示出來,JTune 就是這樣的一種工具(請參閱 參考資料)。觀察 GC 之后堆大小的圖,可以看到程序內(nèi)存使用的趨勢。對于大多數(shù)程序來說,可以將內(nèi)存使用分為兩部分:baseline 使用和 current load 使用。對于服務(wù)器應(yīng)用程序,baseline 使用就是應(yīng)用程序在沒有任何負荷、但是已經(jīng)準備好接受請求時的內(nèi)存使用,current load 使用是在處理請求過程中使用的、但是在請求處理完成后會釋放的內(nèi)存。只要負荷大體上是恒定的,應(yīng)用程序通常會很快達到一個穩(wěn)定的內(nèi)存使用水平。如果在應(yīng)用程序已經(jīng)完成了其初始化并且負荷沒有增加的情況下,內(nèi)存使用持續(xù)增加,那么程序就可能在處理前面的請求時保留了生成的對象。

清單 2 展示了一個有內(nèi)存泄漏的程序。MapLeaker 在線程池中處理任務(wù),并在一個 Map 中記錄每一項任務(wù)的狀態(tài)。不幸的是,在任務(wù)完成后它不會刪除那一項,因此狀態(tài)項和任務(wù)對象(以及它們的內(nèi)部狀態(tài))會不斷地積累。

清單 2. 具有基于 Map 的內(nèi)存泄漏的程序

public class MapLeaker {
public ExecutorService exec = Executors.newFixedThreadPool(5);
public MaptaskStatus
= Collections.synchronizedMap(new HashMap());
private Random random = new Random();

private enum TaskStatus { NOT_STARTED, STARTED, FINISHED };

private class Task implements Runnable {
private int[] numbers = new int[random.nextInt(200)];

public void run() {
int[] temp = new int[random.nextInt(10000)];
taskStatus.put(this, TaskStatus.STARTED);
doSomeWork();
taskStatus.put(this, TaskStatus.FINISHED);
}
}

public Task newTask() {
Task t = new Task();
taskStatus.put(t, TaskStatus.NOT_STARTED);
exec.execute(t);
return t;
}
}
Java中怎么用弱引用堵住內(nèi)存泄漏
確信有了內(nèi)存泄漏后,下一步就是找出哪種對象造成了這個問題。所有內(nèi)存分析器都可以生成按照對象類進行分解的堆快照。有一些很好的商業(yè)堆分析工具,但是找出內(nèi)存泄漏不一定要花錢買這些工具 —— 內(nèi)置的 hprof 工具也可完成這項工作。要使用 hprof 并讓它跟蹤內(nèi)存使用,需要以 -Xrunhprof:heap=sites 選項調(diào)用 JVM。

到此,相信大家對“Java中怎么用弱引用堵住內(nèi)存泄漏”有了更深的了解,不妨來實際操作一番吧!這里是創(chuàng)新互聯(lián)網(wǎng)站,更多相關(guān)內(nèi)容可以進入相關(guān)頻道進行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!


網(wǎng)站名稱:Java中怎么用弱引用堵住內(nèi)存泄漏
文章鏈接:http://weahome.cn/article/gihjcj.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部