<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    海闊天空

    I'm on my way!
    隨筆 - 17, 文章 - 69, 評論 - 21, 引用 - 0
    數據加載中……

    java內存泄漏


    解決Java內存泄漏

    Java內存泄漏是每個Java程序員都會遇到的問題,程序在本地運行一切正常,可是布署到遠端就會出現內存無限制的增長,最后系統癱瘓,那么如何最快最好的檢測程序的穩(wěn)定性,防止系統崩盤,作者用自已的親身經歷與各位分享解決這些問題的辦法.

    作 為Internet最流行的編程語言之一,Java現正非常流行.我們的網絡應用程序就主要采用Java語言開發(fā),大體上分為客戶端、服務器和數據庫三個 層次.在進入測試過程中,我們發(fā)現有一個程序模塊系統內存和CPU資源消耗急劇增加,持續(xù)增長到出現 java.lang.OutOfMemoryError為止.經過分析Java內存泄漏是破壞系統的主要因素.這里與大家分享我們在開發(fā)過程中遇到的 Java內存泄漏的檢測和處理解決過程.

    一. Java是如何管理內存

    為了判斷Java中是否有內存泄露,我們首先必須了解Java是如何管理內存的.Java的內存管理 就是對象的分配和釋放問題.在Java中,內存的分配是由程序完成的,而內存的釋放是由垃圾收集器(Garbage Collection,GC)完成的,程序員不需要通過調用函數來釋放內存,但它只能回收無用并且不再被其它對象引用的那些對象所占用的空間.

    Java的內存垃圾回收機制是從程序的主要運行對象開始檢查引用鏈,當遍歷一遍后發(fā)現沒有被引用的孤 立對象就作為垃圾回收.GC為了能夠正確釋放對象,必須監(jiān)控每一個對象的運行狀態(tài),包括對象的申請、引用、被引用、賦值等,GC都需要進行監(jiān)控.監(jiān)視對象 狀態(tài)是為了更加準確地、及時地釋放對象,而釋放對象的根本原則就是該對象不再被引用.

    在Java中,這些無用的對象都由GC負責回收,因此程序員不需要考慮這部分的內存泄露.雖然,我們 有幾個函數可以訪問GC,例如運行GC的函數System.gc(),但是根據Java語言規(guī)范定義,該函數不保證JVM的垃圾收集器一定會執(zhí)行.因為不 同的JVM實現者可能使用不同的算法管理GC.通常GC的線程的優(yōu)先級別較低.JVM調用GC的策略也有很多種,有的是內存使用到達一定程度時,GC才開 始工作,也有定時執(zhí)行的,有的是平緩執(zhí)行GC,有的是中斷式執(zhí)行GC.但通常來說,我們不需要關心這些.

    二. 什么是Java中的內存泄露

    導致內存泄漏主要的原因是,先前申請了內存空間而忘記了釋放.如果程序中存在對無用對象的引用,那么 這些對象就會駐留內存,消耗內存,因為無法讓垃圾回收器GC驗證這些對象是否不再需要.如果存在對象的引用,這個對象就被定義為"有效的活動",同時不會 被釋放.要確定對象所占內存將被回收,我們就要務必確認該對象不再會被使用.典型的做法就是把對象數據成員設為null或者從集合中移除該對象.但當局部 變量不需要時,不需明顯的設為null,因為一個方法執(zhí)行完畢時,這些引用會自動被清理.

    在Java中,內存泄漏就是存在一些被分配的對象,這些對象有下面兩個特點,首先,這些對象是有被引 用的,即在有向樹形圖中,存在樹枝通路可以與其相連;其次,這些對象是無用的,即程序以后不會再使用這些對象.如果對象滿足這兩個條件,這些對象就可以判 定為Java中的內存泄漏,這些對象不會被GC所回收,然而它卻占用內存.

    這里引用一個常看到的例子,在下面的代碼中,循環(huán)申請Object對象,并將所申請的對象放入一個 Vector中,如果僅僅釋放對象本身,但因為Vector仍然引用該對象,所以這個對象對GC來說是不可回收的.因此,如果對象加入到Vector后, 還必須從Vector中刪除,最簡單的方法就是將Vector對象設置為null.實際上這些對象已經是無用的,但還被引用,GC就無能為力了(事實上 GC認為它還有用),這一點是導致內存泄漏最重要的原因. 再引用另一個例子來說明Java的內存泄漏.假設有一個日志類Logger,其提供一個靜態(tài)的log(String msg),任何其它類都可以調用Logger.Log(message)來將message的內容記錄到系統的日志文件中.

    Logger類有一個類型為HashMap的靜態(tài)變量temp,每次在執(zhí)行l(wèi)og(message) 的時候,都首先將message的值寫入temp中(以當前線程+當前時間為鍵),在退出之前再從temp中將以當前線程和當前時間為鍵的條目刪除.注 意,這里當前時間是不斷變化的,所以log在退出之前執(zhí)行刪除條目的操作并不能刪除執(zhí)行之初寫入的條目.這樣,任何一個作為參數傳給log的字符串最終由 于被Logger的靜態(tài)變量temp引用,而無法得到回收,這種對象保持就是我們所說的Java內存泄漏. 總的來說,內存管理中的內存泄漏產生的主要原因:保留下來卻永遠不再使用的對象引用.

    三. 幾種典型的內存泄漏

    我們知道了在Java中確實會存在內存泄漏,那么就讓我們看一看幾種典型的泄漏,并找出他們發(fā)生的原因和解決方法.

    3.1 全局集合

    在大型應用程序中存在各種各樣的全局數據倉庫是很普遍的,比如一個JNDI-tree或者一個session table.在這些情況下,必須注意管理儲存庫的大小.必須有某種機制從儲存庫中移除不再需要的數據.

    通常有很多不同的解決形式,其中最常用的是一種周期運行的清除作業(yè).這個作業(yè)會驗證倉庫中的數據然后 清除一切不需要的數據.另一種管理儲存庫的方法是使用反向鏈接(referrer)計數.然后集合負責統計集合中每個入口的反向鏈接的數目.這要求反向鏈 接告訴集合何時會退出入口.當反向鏈接數目為零時,該元素就可以從集合中移除了.

    3.2 緩存
    緩存一種用來快速查找已經執(zhí)行過的操作結果的數據結構.因此,如果一個操作執(zhí) 行需要比較多的資源并會多次被使用,通常做法是把常用的輸入數據的操作結果進行緩存,以便在下次調用該操作時使用緩存的數據.緩存通常都是以動態(tài)方式實現 的,如果緩存設置不正確而大量使用緩存的話則會出現內存溢出的后果,因此需要將所使用的內存容量與檢索數據的速度加以平衡.

    常用的解決途徑是使用java.lang.ref.SoftReference類堅持將對象放入緩存.這個方法可以保證當虛擬機用完內存或者需要更多堆的時候,可以釋放這些對象的引用.

    3.3 類裝載器
    Java類裝載器的使用為內存泄漏提供了許多可乘之機.一般來說類裝載器 都具有復雜結構,因為類裝載器不僅僅是只與"常規(guī)"對象引用有關,同時也和對象內部的引用有關.比如數據變量,方法和各種類.這意味著只要存在對數據變 量,方法,各種類和對象的類裝載器,那么類裝載器將駐留在JVM中.既然類裝載器可以同很多的類關聯,同時也可以和靜態(tài)數據變量關聯,那么相當多的內存就 可能發(fā)生泄漏.

    四. 如何檢測和處理內存泄漏

    如何查找引起內存泄漏的原因一般有兩個步驟:第一是安排有經驗的編程人員對代碼進行走查和分析,找出內存泄漏發(fā)生的位置;第二是使用專門的內存泄漏測試工具進行測試.

    第一個步驟:在代碼走查的工作中,可以安排對系統業(yè)務和開發(fā)語言工具比較熟悉的開發(fā)人員對應用的代碼進行了交叉走查,盡量找出代碼中存在的數據庫連接聲明和結果集未關閉、代碼冗余等故障代碼.

    第二個步驟:就是檢測Java的內存泄漏.在這里我們通常使用一些工具來檢查Java程序的內存泄漏 問題.市場上已有幾種專業(yè)檢查Java內存泄漏的工具,它們的基本工作原理大同小異,都是通過監(jiān)測Java程序運行時,所有對象的申請、釋放等動作,將內 存管理的所有信息進行統計、分析、可視化.開發(fā)人員將根據這些信息判斷程序是否有內存泄漏問題.這些工具包括Optimizeit Profiler,JProbe Profiler,JinSight , Rational 公司的Purify等.

    4.1檢測內存泄漏的存在
    這里我們將簡單介紹我們在使用Optimizeit檢查的過程.通常在知道發(fā)生內存泄漏之后,第一步是要弄清楚泄漏了什么數據和哪個類的對象引起了泄漏.

    一般說來,一個正常的系統在其運行穩(wěn)定后其內存的占用量是基本穩(wěn)定的,不應該是無限制的增長的.同 樣,對任何一個類的對象的使用個數也有一個相對穩(wěn)定的上限,不應該是持續(xù)增長的.根據這樣的基本假設,我們持續(xù)地觀察系統運行時使用的內存的大小和各實例 的個數,如果內存的大小持續(xù)地增長,則說明系統存在內存泄漏,如果特定類的實例對象個數隨時間而增長(就是所謂的“增長率”),則說明這個類的實例可能存 在泄漏情況.

    另一方面通常發(fā)生內存泄漏的第一個跡象是:在應用程序中出現了OutOfMemoryError.在 這種情況下,需要使用一些開銷較低的工具來監(jiān)控和查找內存泄漏.雖然OutOfMemoryError也有可能應用程序確實正在使用這么多的內存;對于這 種情況則可以增加JVM可用的堆的數量,或者對應用程序進行某種更改,使它使用較少的內存.

    但是,在許多情況下,OutOfMemoryError都是內存泄漏的信號.一種查明方法是不間斷地監(jiān)控GC的活動,確定內存使用量是否隨著時間增加.如果確實如此,就可能發(fā)生了內存泄漏.

    4.2處理內存泄漏的方法
    一旦知道確實發(fā)生了內存泄漏,就需要更專業(yè)的工具來查明為什么會 發(fā)生泄漏.JVM自己是不會告訴您的.這些專業(yè)工具從JVM獲得內存系統信息的方法基本上有兩種:JVMTI和字節(jié)碼技術(byte code instrumentation).Java虛擬機工具接口(Java Virtual Machine Tools Interface,JVMTI)及其前身Java虛擬機監(jiān)視程序接口(Java Virtual Machine Profiling Interface,JVMPI)是外部工具與JVM通信并從JVM收集信息的標準化接口.字節(jié)碼技術是指使用探測器處理字節(jié)碼以獲得工具所需的信息的技 術.

    Optimizeit是Borland公司的產品,主要用于協助對軟件系統進行代碼優(yōu)化和故障診斷,其中的Optimizeit Profiler主要用于內存泄漏的分析.Profiler的堆視圖就是用來觀察系統運行使用的內存大小和各個類的實例分配的個數的.

    首先,Profiler會進行趨勢分析,找出是哪個類的對象在泄漏.系統運行長時間后可以得到四個內 存快照.對這四個內存快照進行綜合分析,如果每一次快照的內存使用都比上一次有增長,可以認定系統存在內存泄漏,找出在四個快照中實例個數都保持增長的 類,這些類可以初步被認定為存在泄漏.通過數據收集和初步分析,可以得出初步結論:系統是否存在內存泄漏和哪些對象存在泄漏(被泄漏).

    接下來,看看有哪些其他的類與泄漏的類的對象相關聯.前面已經談到Java中的內存泄漏就是無用的對 象保持,簡單地說就是因為編碼的錯誤導致了一條本來不應該存在的引用鏈的存在(從而導致了被引用的對象無法釋放),因此內存泄漏分析的任務就是找出這條多 余的引用鏈,并找到其形成的原因.查看對象分配到哪里是很有用的.同時只知道它們如何與其他對象相關聯(即哪些對象引用了它們)是不夠的,關于它們在何處 創(chuàng)建的信息也很有用.

    最后,進一步研究單個對象,看看它們是如何互相關聯的.借助于Profiler工具,應用程序中的代碼可以在分 配時進行動態(tài)添加,以創(chuàng)建堆棧跟蹤.也有可以對系統中所有對象分配進行動態(tài)的堆棧跟蹤.這些堆棧跟蹤可以在工具中進行累積和分析.對每個被泄漏的實例對 象,必然存在一條從某個牽引對象出發(fā)到達該對象的引用鏈.處于堆棧空間的牽引對象在被從棧中彈出后就失去其牽引的能力,變?yōu)榉菭恳龑ο?因此,在長時間的 運行后,被泄露的對象基本上都是被作為類的靜態(tài)變量的牽引對象牽引.

    總而言之, Java雖然有自動回收管理內存的功能,但內存泄漏也是不容忽視,它往往是破壞系統穩(wěn)定性的重要因素.

     


    摘自:http://www.51testing.com/?88979/spacelist-blog-page-2.html

    posted on 2009-08-24 21:39 石頭@ 閱讀(5109) 評論(1)  編輯  收藏 所屬分類: java_base

    評論

    # re: java內存泄漏  回復  更多評論   

    Java剖析工具JProfiler查找內存泄漏:http://www.evget.com/zh-CN/Info/catalog/18963.html
    2013-05-27 10:49 | mnomo
    主站蜘蛛池模板: 亚洲精品成人网站在线观看| 欧美激情综合亚洲一二区| 四虎国产精品成人免费久久| 成人国产mv免费视频| 亚洲精品第一国产综合亚AV| 永久免费看mv网站入口| 香港经典a毛片免费观看看| 免费人成视网站在线观看不卡| 乱人伦中文视频在线观看免费| 亚洲色偷偷狠狠综合网| a级在线免费观看| 亚洲尹人九九大色香蕉网站| 亚洲高清免费在线观看| 亚洲综合激情五月色一区| 国产成人精品免费直播| 国产午夜无码片免费| 蜜芽亚洲av无码精品色午夜| 无码国产精品一区二区免费I6| 亚洲女子高潮不断爆白浆| 亚洲人成无码www久久久| a毛片全部免费播放| 亚洲校园春色小说| 免费A级毛片在线播放不收费| 日韩a级无码免费视频| 亚洲一区二区三区久久久久| 国产V片在线播放免费无码| 久久久久久a亚洲欧洲aⅴ| 97av免费视频| 亚洲成AV人片在WWW| 中文字幕亚洲不卡在线亚瑟| 50岁老女人的毛片免费观看| 美女免费视频一区二区| 亚洲AV无码久久精品成人| 女人毛片a级大学毛片免费| 一级成人a做片免费| 亚洲另类古典武侠| 亚洲精品岛国片在线观看| 18成禁人视频免费网站| 免费人妻精品一区二区三区| 亚洲首页在线观看| 免费在线观看黄色毛片|