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

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

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

    歲月如哥
    人生非夢
    posts - 50,comments - 144,trackbacks - 0
    轉載:http://hi.baidu.com/coofucoo/blog/item/25d361d9555c002811df9bf2.html

    JVM
    優化配置
    《一》

    OOM這個縮寫就是Java程序開發過程中讓人最頭痛的問題:Out of Memory。在很多開發人員的開發過程中,或多或少的都會遇到這類問題,這類問題定位比較困難,往往需要根據經驗來判斷可能出現問題的代碼。原因主要是 兩個:對象沒有被釋放(多種情況引起,往往是比較隱蔽的引用導致被Hold而無法被回收)。另一種就是真的Memory不夠用了,需要增加JVM的 Heap來滿足應用程序的需求。最近有同事發的關于解決OOM的問題,讓我了解了原來OOM除了在JVM Heap不夠時會發生,在Native Heap不夠的時候也會發生,同時JVM Heap和Native Heap存在著相互影響和平衡的關系,因此就仔細的去看了關于OOM和JVM配置優化的內容。
    OOM
           在 其他語言類似于C,Delphi等等由于內存都是由自己分配和管理,因此內存泄露的問題比較常見,同時也是很頭痛的一件事情。而Java的對象生命周期管 理都是JVM來做的,簡化了開發人員的非業務邏輯的處理,但是這種自動管理回收機制也是基于一些規則的,而違背了這些規則的時候,就會造成所謂的 “Memory Leak”。
    OOM(Java Heap)
           錯誤提示:java.lang.OutOfMemoryError。
    這 類OOM是由于JVM分配的給應用的Heap Memory已經被耗盡,可能是因為應用在高負荷的情況下的卻需要很大的內存,因此可以通過修改JVM參數來增加Java Heap Memory(不過也不能無限制增加,后面那種OOM有可能就是因為這個原因而產生)。另一種情況是因為應用程序使用對象或者資源沒有釋放,導致內存消耗 持續增加,最后出現OOM,這類問題引起的原因往往是應用已不需要的對象還被其他有效對象所引用,那么就無法釋放,可能是業務代碼邏輯造成的(異常處理不 夠例如IO等資源),也可能是對于第三方開源項目中資源釋放了解不夠導致使用以后資源沒有釋放(例如JDBC的ResultSet等)。
           幾個容易出現問題的場景:
           1.應用的緩存或者Collection:如果應用要緩存Java對象或者是在一個Collection中保存對象,那么就要確定是否會有大量的對象存入,要做保護,以防止在大數據量下大量內存被消耗,同時要保證Cache的大小不會無限制增加。
           2.生命周期較長的對象:盡量簡短對象的生命周期,現在采用對象的創建釋放代價已經很低,同時作了很好的優化,要比創建一個對象長期反復使用要好。如果能夠設置超時的情景下,盡量設置超時。
           3.類似于JDBC的Connection Pool,在使用Pool中的對象以后需要釋放并返回,不然就會造成Pool的不斷增大,在其他Pool中使用也是一樣。同樣ResultSet,IO這類資源的釋放都需要注意。
           解決的方法就是查找錯誤或者是增加Java Heap Memory。對于此類問題檢測工具相當多,這里就不做介紹了。      
    OOM(Native Heap)
    錯誤提示:requested XXXX bytes for ChunkPool::allocate. Out of swap space。
           Native Heap Memory是JVM 內部使用的Memory,這部分的Memory可以通過JDK提供的JNI的方式去訪問,這部分Memory效率很高,但是管理需要自己去做,如果沒有把 握最好不要使用,以防出現內存泄露問題。JVM 使用Native Heap Memory用來優化代碼載入(JTI代碼生成),臨時對象空間申請,以及JVM內部的一些操作。這次同事在壓力測試中遇到的問題就是這類OOM,也就是 這類Memory耗盡。同樣這類OOM產生的問題也是分成正常使用耗盡和無釋放資源耗盡兩類。無釋放資源耗盡很多時候不是程序員自身的原因,可能是引用的 第三方包的缺陷,例如很多人遇到的Oracle 9 JDBC驅動在低版本中有內存泄露的問題。要確定這類問題,就需要去觀察Native Heap Memory的增長和使用情況,在服務器應用起來以后,運行一段時間后JVM對于Native Heap Memory的使用會達到一個穩定的階段,此時可以看看什么操作對于Native Heap Memory操作頻繁,而且使得Native Heap Memory增長,對于Native Heap Memory的情況我還沒有找到辦法去檢測,現在能夠看到的就是為JVM啟動時候增加-verbose:jni參數來觀察對于Native Heap Memory的操作。另一種情況就是正常消耗Native Heap Memory,對于Native Heap Memory的使用主要取決于JVM代碼生成,線程創建,用于優化的臨時代碼和對象產生。當正常耗盡Native Heap Memory時,那么就需要增加Native Heap Memory,此時就會和我們前面提到增加java Heap Memory的情況出現矛盾。
    應用內存組合
           對 于應用來說,可分配的內存受到OS的限制,不同的OS對進程所能訪問虛擬內存地址區間直接影響對于應用內存的分配,32位的操作系統通常最大支持4G的內 存尋址,而Linux一般為3G,Windows為2G。然而這些大小的內存并不會全部給JVM的Java Heap使用,它主要會分成三部分:Java Heap,Native Heap,載入資源和類庫等所占用的內存。那么由此可見,Native Heap和 Java Heap大小配置是相互制約的,哪一部分分配多了都可能會影響到另外一部分的正常工作,因此如果通過命令行去配置,那么需要確切的了解應用使用情況,否則 采用默認配置自動監測會更好的優化應用使用情況。
           同樣要注意的就是進程的虛擬內存和機器的實際內存還是有區別的,對于機器來說實際內存以及硬盤提供的虛擬內存都是提供給機器上所有進程使用的,因此在設置JVM參數時,它的虛擬內存絕對不應該超過實際內存的大小。
    《二》
           這 里首先要說明的是這里提到的JVM是Sun的HotSpot JVM 5和以上的版本。性能優化在應用方面可以有很多手段,包括Cache,多線程,各種算法等等。通常情況下是不建議在沒有任何統計和分析的情況下去手動配置 JVM的參數來調整性能,因為在JVM 5以上已經作了根據機器和OS的情況自動配置合適參數的算法,基本能夠滿足大部分的情況,當然這種自動適配只是一種通用的方式,如果說真的要達到最優,那 么還是需要根據實際的使用情況來手動的配置各種參數設置,提高性能。
           JVM能夠對性能產生影響的最大部分就是對于內存的管理。從jdk 1.5以后內存管理和分配有了很多的改善和提高。
    內存分配以及管理的幾個基本概念和參數說明:
    Java Hotspot Mode:
    server 和 client兩種模式,如果不配置,JVM會根據應用服務器硬件配置自動選擇模式,server模式啟動比較慢,但是運行期速度得到了優化,client啟動比較快,但是運行期響應沒有server模式的優化,適合于個人PC的服務開發和測試。
    Garbage Collector Policy:
           在Jdk 1.5的時候已經提供了三種GC,除了原來提供的串行GC(SerialGC)以外,還提供了兩種新的GC:ParallelGC和 ConcMarkSweepGC。ParallelGC采用了多線程并行管理和回收垃圾對象,提高了回收效率,提高了服務器的吞吐量,適合于多處理器的服 務器。ConcMarkSweepGC采用的是并發方式來管理和回收垃圾對象,降低垃圾回收產生的響應暫停時間。這里說一下并發和并行的區別,并發指的是 多個進程并行執行垃圾回收,那么可以很好的利用多處理器,而并行指的是應用程序不需要暫停可以和垃圾回收線程并發工作。串行GC適合小型應用和單處理器系 統(無需多線程交互,效率比較高),后兩者適合大型系統。
           使用方式就是在參數配置中增加-XX:+UseParallelGC等方式來設置。
           對于這部分的配置在網上有很多的實例可以參考,不過最終采用哪一種GC還是要根據具體的情況來分析和選擇。
    Heap:
           OOM的 各種經歷已經讓每一個架構師開發人員看到了了解Heap的重要性。OOM已經是Heap的臨界點,不得不引起注意,然而Heap對于性能的潛在影響并未被 引起重視,不過和GC配置一樣,在沒有對使用情況作仔細分析和研究的情況下,貿然的去修改Heap配置,可能適得其反,這里就來看一下Heap的一些概念 和對于性能的影響。
           我們的應用所能夠得到的最大的Heap受三部分因素的制約:數據處理 模型(32位或者64位操作系統),系統地虛擬內存總數和系統的物理內存總數。首先Heap的大小不能超過不同操作系統的進程尋址范圍,當前大部分系統最 高限度是4G,Windows通常是2G,Linux通常是3G。系統的虛擬內存也是分配的依據,首先是不能超過,然后由于操作系統支持硬盤來做部分的虛 擬內存,如果設置過大,那么對于應用響應來說勢必有影響。再則就是要考慮同一臺服務器上運行多個Java虛擬機所消耗的資源總合也不能超過可用資源。就和 前面OOM分析中的一樣,其實由于OS的數據處理模型的限制,機器本身的硬件內存資源和虛擬內存資源并不一定會匹配,那么在有限的資源下如何調整好資源分 配,對于應用來說尤為重要。
    關于Heap的幾個參數設置:
           說了Heap的有限資源問題以后,就來看看如何通過配置去改變JVM對于Heap的分配。下面所說的主要是對于Java Heap的分配,那么在申請了Java Heap以后,剩下的可用資源就會被使用到Native Heap。
           Xms: java heap初始化時的大小。默認情況是機器物理內存的1/64。這個主要是根據應用啟動時消耗的資源決定,分配少了申請起來會降低啟動速度,分配多了也浪費。
           Xmx:java heap的 最大值,默認是機器物理內存的1/4,最大也就到1G。這個值決定了最多可用的Java Heap Memory,分配過少就會在應用需要大量內存作緩存或者零時對象時出現OOM的問題,如果分配過大,那么就會產生上文提到的第二類OOM。所以如何配置 還是根據運行過程中的分析和計算來確定,如果不能確定還是采用默認的配置。
           Xmn:java heap新 生代的空間大小。在GC模型中,根據對象的生命周期的長短,產生了內存分代的設計:青年代(內部也分成三部分,類似于整體劃分的作用,可以通過配置來設置 比例),老年代,持久代。每一代的管理和回收策略都不相同,最為活躍的就是青年代,同時這部分的內存分配和管理效率也是最高。通常情況下,對于內存的申請 優先在新生代中申請,當內存不夠時會整理新生代,當整理以后還是不能滿足申請的內存,就會向老年代移動一些生命周期較長的對象。這種整理和移動會消耗資 源,同時降低系統運行響應能力,因此如果青年代設置的過小,就會頻繁的整理和移動,對性能造成影響。那是否把年青代設置的越大越好,其實不然,年青代采用 的是復制搜集算法,這種算法必須停止所有應用程序線程,服務器線程切換時間就會成為應用響應的瓶頸(當然永遠不用收集那么就不存在這個問題)。老年代采用 的是串行標記收集的方式,并發收集可以減少對于應用的影響。
           Xss:線程堆棧最大值。允許更多的虛擬內存空間地址被Java Heap使用。
    以下是sun公司的性能優化白皮書中提到的幾個例子:
    1.對于吞吐量的調優。機器配置:4G的內存,32個線程并發能力。
    java -Xmx3800m -Xms3800m -Xmn2g -Xss128k -XX:+UseParallelGC -XX:ParallelGCThreads=20
           -Xmx3800m -Xms3800m 配置了最大Java Heap來充分利用系統內存。
           -Xmn2g 創建足夠大的青年代(可以并行被回收)充分利用系統內存,防止將短期對象復制到老年代。
        -Xss128 減少默認最大的線程棧大小,提供更多的處理虛擬內存地址空間被進程使用。
        -XX:+UseParallelGC 采用并行垃圾收集器對年青代的內存進行收集,提高效率。
        -XX:ParallelGCThreads=20 減少垃圾收集線程,默認是和服務器可支持的線程最大并發數相同,往往不需要配置到最大值。
    2.嘗試采用對老年代并行收集
    java -Xmx3550m -Xms3550m -Xmn2g -Xss128k -XX:+UseParallelGC -XX:ParallelGCThreads=20 -XX:+UseParallelOldGC
    -Xmx3550m -Xms3550m 內存分配被減小,因為ParallelOldGC會增加對于Native Heap的需求,因此需要減小Java Heap來滿足需求。
    -XX:+UseParallelOldGC 采用對于老年代并發收集的策略,可以提高收集效率。
    3.提高吞吐量,減少應用停頓時間
    java -Xmx3550m -Xms3550m -Xmn2g -Xss128k -XX:ParallelGCThreads=20 -XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:SurvivorRatio=8 -XX:TargetSurvivorRatio=90 -XX:MaxTenuringThreshold=31
    -XX:+UseConcMarkSweepGC -XX:+UseParNewGC 選擇了并發標記交換收集器,它可以并發執行收集操作,降低應用停止時間,同時它也是并行處理模式,可以有效地利用多處理器的系統的多進程處理。
    -XX:SurvivorRatio=8 -XX:MaxTenuringThreshold=31 表示在青年代中Eden和Survivor比例,設置增加了Survivor的大小,越大的survivor空間可以允許短期對象盡量在年青代消亡。
    -XX:TargetSurvivorRatio=90 允許90%的空間被占用,超過默認的50%,提高對于survivor的使用率。
    類似的例子網上很多,這兒就不在列下來了,最終是否采取自己配置來替換默認配置還是要根據虛擬機的使用情況來分析和配置。

    posted on 2008-09-21 18:13 歲月如歌 閱讀(1667) 評論(2)  編輯  收藏 所屬分類: java

    FeedBack:
    # re: OOM和JVM優化配置 zz
    2008-10-03 21:59 | 殺手
    QQ幣  回復  更多評論
      
    # re: OOM和JVM優化配置 zz[未登錄]
    2013-11-12 10:33 | QQ
    luguo  回復  更多評論
      
    主站蜘蛛池模板: 久久精品国产亚洲沈樵| 国产91在线免费| 亚洲欧洲美洲无码精品VA| 中美日韩在线网免费毛片视频| 国产真实伦在线视频免费观看| 亚洲国产日韩精品| 大陆一级毛片免费视频观看i| 亚洲精品人成网在线播放影院 | 久久国产精品免费看| 亚洲V无码一区二区三区四区观看| 中文字幕乱码免费看电影| 亚洲精品无码Av人在线观看国产| 中文字幕乱码一区二区免费| 亚洲AV无码国产在丝袜线观看| 三年片在线观看免费观看大全一| 亚洲天堂男人天堂| 青青视频观看免费99| 亚洲乱码av中文一区二区| 亚洲AⅤ无码一区二区三区在线| fc2成年免费共享视频网站| 久久久亚洲欧洲日产国码农村| 91热久久免费精品99| 亚洲人AV在线无码影院观看| 免费A级毛片无码久久版| 精品国产福利尤物免费| 蜜芽亚洲av无码精品色午夜| 我要看免费的毛片| 一级毛片免费在线观看网站| 精品国产亚洲一区二区三区| 久草视频免费在线| 国产亚洲视频在线观看网址| 亚洲国产精品无码久久一线| 性色av无码免费一区二区三区| 西西人体大胆免费视频| 亚洲av无码潮喷在线观看| 午夜男人一级毛片免费| a级毛片免费全部播放无码| 亚洲另类视频在线观看| 亚洲色欲久久久久综合网| 2019中文字幕免费电影在线播放| 亚洲乱码av中文一区二区|