熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Java編程 >> Java核心技術 >> 正文

深入Java虛擬機之內存優化

2013-11-23 19:07:39  來源: Java核心技術 
    眾所周知Java是從C++的基礎上發展而來的而C++程序的很大的一個問題就是內存洩露難以解決盡管Java的JVM有一套自己的垃圾回收機制來回收內存在許多情況下並不需要java程序開發人員操太多的心但也是存在洩露問題的只是比C++小一點比如說程序中存在被引用但無用的對象程序引用了該對象但後續不會或者不能再使用它那麼它占用的內存空間就浪費了
   
    我們先來看看GC是如何工作的監控每一個對象的運行狀態包括對象的申請引用被引用賦值等當該對象不再被引用時釋放對象(GC本文的重點不做過多闡述)很多Java程序員過分依賴GC但問題的關鍵是無論JVM的垃圾回收機制做得多好內存總歸是有限的資源因此就算GC會為我們完成了大部分的垃圾回收但適當地注意編碼過程中的內存優化還是很必要的這樣可以有效的減少GC次數同時提升內存利用率最大限度地提高程序的效率
   
    總體而言Java虛擬機的內存優化應從兩方面著手Java虛擬機和Java應用程序前者指根據應用程序的設計通過虛擬機參數控制虛擬機邏輯內存分區的大小以使虛擬機的內存與程序對內存的需求相得益彰後者指優化程序算法降低GC負擔提高GC回收成功率
   
    通過參數優化虛擬機內存的參數如下所示
   
    ◆  Xms
   
    初始Heap大小
   
    ◆ Xmx
   
    java heap最大值
   
    ◆ Xmn
   
    young generation的heap大小
   
    ◆ Xss
   
    每個線程的Stack大小
   
    上面是三個比較常用的參數還有一些
   
    ◆ XX:MinHeapFreeRatio=
   
    Minimum percentage of heap free after GC to avoid expansion
   
    ◆ XX:MaxHeapFreeRatio=
   
    Maximum percentage of heap free after GC to avoid shrinking
   
    ◆ XX:NewRatio=
   
    Ratio of new/old generation sizes [Sparc client:; x server:; x client:]client:+) x:]
   
    ◆ XX:NewSize=m
   
    Default size of new generation (in bytes) [ and newer: bit VMs are scaled % larger; x:m; x and older: k]
   
    ◆ XX:MaxNewSize=
   
    Maximum size of new generation (in bytes) Since MaxNewSize is computed as a function of NewRatio
   
    ◆ XX:SurvivorRatio=
   
    Ratio of eden/survivor space size [Solaris amd: ; Sparc in : ; other Solaris platforms in and earlier: ]
   
    ◆ XX:PermSize=
   
    Initial size of permanent generation
   
    ◆ XX:MaxPermSize=m
   
    Size of the Permanent Generation [ and newer: bit VMs are scaled % larger; amd: m; client: m]
   
    下面所說通過優化程序算法來提高內存利用率並降低內存風險完全是經驗之談僅供參考如有不妥請指正謝謝!
   
    盡早釋放無用對象的引用(XX = null;)
   
    看一段代碼
   
    public List<PageData> parse(HtmlPage page) {
   
    List<PageData> list = null;
   
    try {
   
    List valueList = pagegetByXPath(configgetContentXpath())
   
    if (valueList == null || valueListisEmpty()) {
   
    return list;
   
    }
   
    //需要時才創建對象節省內存提高效率
   
    list = new ArrayList<PageData>()
   
    PageData pageData = new PageData()
   
    StringBuilder value = new StringBuilder()
   
    for (int i = ; i < valueListsize() i++) {
   
    HtmlElement content = (HtmlElement) valueListget(i)
   
    DomNodeList<HtmlElement> imgs = contentgetElementsByTagName(img
   
    if (imgs != null && !imgsisEmpty()) {
   
    for (HtmlElement img : imgs) {
   
    try {
   
    HtmlImage image = (HtmlImage) img;
   
    String path = imagegetSrcAttribute()
   
    String format = pathsubstring(pathlastIndexOf( pathlength())
   
    String localPath = D:/images/ + MDHelpermd(path)replace(\\ replace(/ ) + format;
   
    File localFile = new File(localPath)
   
    if (!localFileexists()) {
   
    localFilecreateNewFile()
   
    imagesaveAs(localFile)
   
    }
   
    imagesetAttribute(src file:/// + localPath)
   
    localFile = null;
   
    image = null;
   
    img = null;
   
    } catch (Exception e) {
   
    }
   
    }
   
    //這個對象以後不會在使用了清除對其的引用等同於提前告知GC該對象可以回收了
   
    imgs = null;
   
    }
   
    String text = contentasXml()
   
    valueappend(text)append(<br/>
   
    valueList=null;
   
    content = null;
   
    text = null;
   
    }
   
    pageDatasetContent(valuetoString())
   
    pageDatasetCharset(pagegetPageEncoding())
   
    listadd(pageData)
   
    //這裡 pageData=null; 是沒用的因為list仍然持有該對象的引用GC不會回收它
   
    value=null;
   
    //這裡可不能 list=null; 因為list是方法的返回值否則你從該方法中得到的返回值永遠為空而且這種錯誤不易被發現排除
   
    } catch (Exception e) {
   
    }
   
    return list;
   
    }
   
    謹慎使用集合數據類型如數組鏈表等數據結構這些數據結構對GC來說回收更復雜
   
    避免顯式申請數組空間不得不顯式申請時盡量准確估計其合理值
   
    盡量避免在類的默認構造器中創建初始化大量的對象防止在調用其自類的構造器時造成不必要的內存資源浪費
   
    盡量避免強制系統做垃圾內存的回收增長系統做垃圾回收的最終時間
   
    盡量做遠程方法調用類應用開發時使用瞬間值變量除非遠程調用端需要獲取該瞬間值變量的值
   
    盡量在合適的場景下使用對象池技術以提高系統性能
From:http://tw.wingwit.com/Article/program/Java/hx/201311/26308.html
    推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.