<nobr id="rub96"><optgroup id="rub96"></optgroup></nobr>

    <bdo id="rub96"></bdo>

      1. <track id="rub96"><div id="rub96"></div></track>
        <nobr id="rub96"><optgroup id="rub96"></optgroup></nobr>

            <nobr id="rub96"><address id="rub96"><big id="rub96"></big></address></nobr>
          1. <menuitem id="rub96"><strong id="rub96"><menu id="rub96"></menu></strong></menuitem>
            <dl id="rub96"><source id="rub96"><tr id="rub96"></tr></source></dl>
            1. <tbody id="rub96"><div id="rub96"></div></tbody>
              1. <bdo id="rub96"><optgroup id="rub96"></optgroup></bdo>
              2. <bdo id="rub96"><dfn id="rub96"><dd id="rub96"></dd></dfn></bdo>
                1. <option id="rub96"><source id="rub96"></source></option>
                2. <bdo id="rub96"></bdo>

                    <p id="rub96"><tr id="rub96"></tr></p>
                  1. <tbody id="rub96"></tbody>

                    <bdo id="rub96"></bdo>

                  2. <option id="rub96"><source id="rub96"></source></option>

                    <bdo id="rub96"><optgroup id="rub96"><dd id="rub96"></dd></optgroup></bdo>
                      <track id="rub96"></track>

                        <bdo id="rub96"></bdo>
                      1. <option id="rub96"><p id="rub96"><tr id="rub96"></tr></p></option>

                          <bdo id="rub96"></bdo>
                          1. <track id="rub96"></track>
                            1. <track id="rub96"></track>
                                  <bdo id="rub96"></bdo>
                                  <option id="rub96"></option>

                                      1. <track id="rub96"><span id="rub96"></span></track>

                                          <option id="rub96"></option>

                                          1. 
                                            
                                              <option id="rub96"><span id="rub96"></span></option>
                                              <bdo id="rub96"><address id="rub96"></address></bdo>
                                              <option id="rub96"><source id="rub96"></source></option>
                                                <nobr id="rub96"><address id="rub96"></address></nobr>
                                              1. <nobr id="rub96"><optgroup id="rub96"><big id="rub96"></big></optgroup></nobr>
                                                <track id="rub96"></track>

                                                <nobr id="rub96"><optgroup id="rub96"></optgroup></nobr>
                                                1. 成都心情

                                                    BlogJava :: 首頁 ::  :: 聯系 :: 聚合  :: 管理 ::
                                                    98 隨筆 :: 2 文章 :: 501 評論 :: 1 Trackbacks

                                                  前言的前言:本文是自20058月以來,首次在一個月之內發布三篇文章。謹以此文獻給這么多年始終不濟的我。所謂少不入川,而今已非年少。北漂快兩年了,何時能回到故鄉,回去后又會怎樣,也許永遠是個未知……

                                                   

                                                  前言

                                                   

                                                  在平時工作過程中,有時會遇到OutOfMemoryError,我們知道遇到Error一般表明程序存在著嚴重問題,可能是災難性的。所以找出是什么原因造成OutOfMemoryError非常重要。現在向大家引薦Eclipse Memory Analyzer tool(MAT),來化解我們遇到的難題。如未說明,本文均使用Java 5.0 on Windows XP SP3環境。

                                                   

                                                  為什么用MAT

                                                   

                                                  之前的觀點,我認為使用實時profiling/monitoring之類的工具,用一種非常實時的方式來分析哪里存在內存泄漏是很正確的。年初使用了某profiler工具測試消息中間件中存在的內存泄漏,發現在吞吐量很高的時候profiler工具自己也無法響應,這讓人很頭痛。后來了解到這樣的工具本身就要消耗性能,且在某些條件下還發現不了泄漏。所以,分析離線數據就非常重要了,MAT正是這樣一款工具。

                                                   

                                                  為何會內存溢出

                                                   

                                                  我們知道JVM根據generation()來進行GC,根據下圖所示,一共被分為young generation(年輕代)tenured generation(老年代)permanent generation(永久代, perm gen)perm gen(或稱Non-Heap 非堆)是個異類,稍后會講到。注意,heap空間不包括perm gen


                                                  絕大多數的對象都在young generation被分配,也在young generation被收回,當young generation的空間被填滿,GC會進行minor collection(次回收),這次回收不涉及到heap中的其他generationminor collection根據weak generational hypothesis(弱年代假設)來假設young generation中大量的對象都是垃圾需要回收,minor collection的過程會非常快。young generation中未被回收的對象被轉移到tenured generation,然而tenured generation也會被填滿,最終觸發major collection(主回收),這次回收針對整個heap,由于涉及到大量對象,所以比minor collection慢得多。

                                                   

                                                  JVM有三種垃圾回收器,分別是throughput collector,用來做并行young generation回收,由參數-XX:+UseParallelGC啟動;concurrent low pause collector,用來做tenured generation并發回收,由參數-XX:+UseConcMarkSweepGC啟動;incremental low pause collector,可以認為是默認的垃圾回收器。不建議直接使用某種垃圾回收器,最好讓JVM自己決斷,除非自己有足夠的把握。

                                                   

                                                  Heap中各generation空間是如何劃分的?通過JVM-Xmx=n參數可指定最大heap空間,而-Xms=n則是指定最小heap空間。在JVM初始化的時候,如果最小heap空間小于最大heap空間的話,如上圖所示JVM會把未用到的空間標注為Virtual。除了這兩個參數還有-XX:MinHeapFreeRatio=n -XX:MaxHeapFreeRatio=n來分別控制最大、最小的剩余空間與活動對象之比例。在32Solaris SPARC操作系統下,默認值如下,在32windows xp下,默認值也差不多。


                                                  參數

                                                  默認值

                                                  MinHeapFreeRatio

                                                  40

                                                  MaxHeapFreeRatio

                                                  70

                                                  -Xms

                                                  3670k

                                                  -Xmx

                                                  64m


                                                  由于tenured generationmajor collection較慢,所以tenured generation空間小于young generation的話,會造成頻繁的major collection,影響效率。Server JVM默認的young generationtenured generation空間比例為1:2,也就是說young generationedensurvivor空間之和是整個heap(當然不包括perm gen)的三分之一,該比例可以通過-XX:NewRatio=n參數來控制,而Client JVM默認的-XX:NewRatio8。至于調整young generation空間大小的NewSize=nMaxNewSize=n參數就不講了,請參考后面的資料。

                                                   

                                                  young generation中幸存的對象被轉移到tenured generation,但不幸的是concurrent collector線程在這里進行major collection,而在回收任務結束前空間被耗盡了,這時將會發生Full Collections(Full GC),整個應用程序都會停止下來直到回收完成。Full GC是高負載生產環境的噩夢……

                                                   

                                                  現在來說說異類perm gen,它是JVM用來存儲無法在Java語言級描述的對象,這些對象分別是類和方法數據(與class loader有關)以及interned strings(字符串駐留)。一般32OSperm gen默認64m,可通過參數-XX:MaxPermSize=n指定,JVM Memory Structure一文說,對于這塊區域,沒有更詳細的文獻了,神秘。

                                                   

                                                  回到問題“為何會內存溢出?”。

                                                  要回答這個問題又要引出另外一個話題,既什么樣的對象GC才會回收?當然是GC發現通過任何reference chain(引用鏈)無法訪問某個對象的時候,該對象即被回收。名詞GC Roots正是分析這一過程的起點,例如JVM自己確保了對象的可到達性(那么JVM就是GC Roots),所以GC Roots就是這樣在內存中保持對象可到達性的,一旦不可到達,即被回收。通常GC Roots是一個在current thread(當前線程)call stack(調用棧)上的對象(例如方法參數和局部變量),或者是線程自身或者是system class loader(系統類加載器)加載的類以及native code(本地代碼)保留的活動對象。所以GC Roots是分析對象為何還存活于內存中的利器。知道了什么樣的對象GC才會回收后,再來學習下對象引用都包含哪些吧。

                                                   

                                                  從最強到最弱,不同的引用(可到達性)級別反映了對象的生命周期。

                                                  l  Strong Ref(強引用):通常我們編寫的代碼都是Strong Ref,于此對應的是強可達性,只有去掉強可達,對象才被回收。

                                                  l  Soft Ref(軟引用):對應軟可達性,只要有足夠的內存,就一直保持對象,直到發現內存吃緊且沒有Strong Ref時才回收對象。一般可用來實現緩存,通過java.lang.ref.SoftReference類實現。

                                                  l  Weak Ref(弱引用):比Soft Ref更弱,當發現不存在Strong Ref時,立刻回收對象而不必等到內存吃緊的時候。通過java.lang.ref.WeakReferencejava.util.WeakHashMap類實現。

                                                  l  Phantom Ref(虛引用):根本不會在內存中保持任何對象,你只能使用Phantom Ref本身。一般用于在進入finalize()方法后進行特殊的清理過程,通過 java.lang.ref.PhantomReference實現。

                                                   

                                                  有了上面的種種我相信很容易就能把heapperm gen撐破了吧,是的利用Strong Ref,存儲大量數據,直到heap撐破;利用interned strings(或者class loader加載大量的類)把perm gen撐破。

                                                   

                                                  關于shallow sizeretained size

                                                   

                                                  Shallow size就是對象本身占用內存的大小,不包含對其他對象的引用,也就是對象頭加成員變量(不是成員變量的值)的總和。在32位系統上,對象頭占用8字節,int占用4字節,不管成員變量(對象或數組)是否引用了其他對象(實例)或者賦值為null它始終占用4字節。故此,對于String對象實例來說,它有三個int成員(3*4=12字節)、一個char[]成員(1*4=4字節)以及一個對象頭(8字節),總共3*4 +1*4+8=24字節。根據這一原則,對String a=”rosen jiang”來說,實例ashallow size也是24字節(很多人對此有爭議,請看官甄別并留言給我)。

                                                   

                                                  Retained size是該對象自己的shallow size,加上從該對象能直接或間接訪問到對象的shallow size之和。換句話說,retained size是該對象被GC之后所能回收到內存的總和。為了更好的理解retained size,不妨看個例子。

                                                   

                                                  把內存中的對象看成下圖中的節點,并且對象和對象之間互相引用。這里有一個特殊的節點GC Roots,正解!這就是reference chain的起點。

                                                  retained_objects.gifretained_objects_2.gif

                                                  obj1入手,上圖中藍色節點代表僅僅只有通過obj1才能直接或間接訪問的對象。因為可以通過GC Roots訪問,所以左圖的obj3不是藍色節點;而在右圖卻是藍色,因為它已經被包含在retained集合內。

                                                  所以對于左圖,obj1retained sizeobj1obj2obj4shallow size總和;右圖的retained sizeobj1obj2obj3obj4shallow size總和。obj2retained size可以通過相同的方式計算。

                                                   

                                                  Heap Dump

                                                   

                                                  heap dump是特定時間點,java進程的內存快照。有不同的格式來存儲這些數據,總的來說包含了快照被觸發時java對象和類在heap中的情況。由于快照只是一瞬間的事情,所以heap dump中無法包含一個對象在何時、何地(哪個方法中)被分配這樣的信息。

                                                   

                                                  在不同平臺和不同java版本有不同的方式獲取heap dump,而MAT需要的是HPROF格式的heap dump二進制文件。想無需人工干預的話,要這樣配置JVM參數:-XX:-HeapDumpOnOutOfMemoryError,當錯誤發生時,會自動生成heap dump,在生產環境中,只有用這種方式。如果你想自己控制什么時候生成heap dump,在Windows+JDK6環境中可利用JConsole工具,而在Linux或者Mac OS X環境下均可使用JDK56自帶的jmap工具。當然,還可以配置JVM參數:-XX:+HeapDumpOnCtrlBreak,也就是在控制臺使用Ctrl+Break鍵來生成heap dump。由于我是windows+JDK5,所以選擇了-XX:-HeapDumpOnOutOfMemoryError這種方式,更多配置請參考MAT Wiki

                                                   

                                                  參考資料

                                                   

                                                  MAT Wiki

                                                  Interned Strings

                                                  Strong,Soft,Weak,Phantom Reference

                                                  Tuning Garbage Collection with the 5.0 Java[tm] Virtual Machine

                                                  Permanent Generation

                                                  Understanding Weak References譯文

                                                  Java HotSpot VM Options

                                                  Shallow and retained sizes

                                                  JVM Memory Structure

                                                  GC roots


                                                  請注意!引用、轉貼本文應注明原作者:Rosen Jiang 以及出處: http://www.ymeg.top/rosen

                                                  posted on 2010-05-21 20:59 Rosen 閱讀(71343) 評論(23)  編輯  收藏 所屬分類: Java 基礎

                                                  評論

                                                  # re: 使用Memory Analyzer tool(MAT)分析內存泄漏(一) 2010-05-23 18:20 BeanSoft
                                                  好好干! 前途是光明的! 當然, 在京買房就別考慮了, 不現實!  回復  更多評論
                                                    

                                                  # re: 使用Memory Analyzer tool(MAT)分析內存泄漏(一) 2010-05-24 09:51 Rosen
                                                  @BeanSoft
                                                  感謝BeanSoft兄關心,主要還是不會混,也錯過一次次的機會。
                                                  是啊,是要為后路考慮了。  回復  更多評論
                                                    

                                                  # re: 使用Memory Analyzer tool(MAT)分析內存泄漏(一) 2010-05-25 15:02 liucr
                                                  很精辟,感謝博主,你的前途一定會有。  回復  更多評論
                                                    

                                                  # re: 使用Memory Analyzer tool(MAT)分析內存泄漏(一) 2010-12-15 09:15 Rosen
                                                  @李文棟
                                                  我是成都人,目前還是有6年工作時間了。  回復  更多評論
                                                    

                                                  # re: 使用Memory Analyzer tool(MAT)分析內存泄漏(一) 2010-12-15 16:55 Rayleeya
                                                  @Rosen
                                                  多謝大蝦的博文。
                                                    回復  更多評論
                                                    

                                                  # re: 使用Memory Analyzer tool(MAT)分析內存泄漏(一) 2011-01-26 17:31 耿恬
                                                  不錯,受益匪淺。樓主這能力不要擔心前途  回復  更多評論
                                                    

                                                  # re: 使用Memory Analyzer tool(MAT)分析內存泄漏(一) 2011-04-21 19:51 morning5607
                                                  膜拜,同是成都人!  回復  更多評論
                                                    

                                                  # re: 使用Memory Analyzer tool(MAT)分析內存泄漏(一) 2011-08-29 16:10 lijunwyf22
                                                  很不錯,值得收藏。  回復  更多評論
                                                    

                                                  # re: 使用Memory Analyzer tool(MAT)分析內存泄漏(一) 2011-10-19 18:14 fan
                                                  嘻嘻  回復  更多評論
                                                    

                                                  # re: 使用Memory Analyzer tool(MAT)分析內存泄漏(一) 2012-03-12 14:11 Locke
                                                  首先謝謝樓主關于MAT的介紹。
                                                  有一點,-XX:+HeapDumpOnCtrlBreak這個參數在JDK6里面應該是被取消了。我本地是JDK6_29版本。  回復  更多評論
                                                    

                                                  # re: 使用Memory Analyzer tool(MAT)分析內存泄漏(一)[未登錄] 2012-06-27 11:23 IT民工
                                                  最后也沒說。是什么引發內存泄露。。  回復  更多評論
                                                    

                                                  # re: 使用Memory Analyzer tool(MAT)分析內存泄漏(一) 2012-07-18 17:40 ureygo
                                                  說的不錯,長知識了  回復  更多評論
                                                    

                                                  # re: 使用Memory Analyzer tool(MAT)分析內存泄漏(一)[未登錄] 2012-11-19 11:55 william
                                                  有一個問題想要請教一下:在圖2中假設

                                                  obj1的shallow size = 1024b,
                                                  obj2的shallow size = 1024b,
                                                  obj3的shallow size = 1024b,
                                                  obj4的shallow size = 1024b, 那么,按照您的算法:

                                                  obj1的retain size = 4096b,
                                                  obj2的retain size = 3072b,
                                                  obj3的retain size = 1024b,
                                                  obj3的retain size = 1024b,

                                                  那實際的內存占用大小是多少呢?

                                                  1:4096+3027+1024+1024?
                                                  2:1024+4*1 + 1024+4*2 + 1024 + 1024?

                                                    回復  更多評論
                                                    

                                                  # re: 使用Memory Analyzer tool(MAT)分析內存泄漏(一) 2012-12-19 09:37 shuhucy
                                                  -XX:-HeapDumpOnOutOfMemoryError

                                                  這個配置是錯的,正確的配置是:

                                                  -XX:+HeapDumpOnOutOfMemoryError

                                                  這樣才會打印堆轉儲文件

                                                  同時建議配置:
                                                  -XX:HeapDumpPath=D:\heapdump選項,指定文件目錄,不然轉儲文件輸出到什么地方了,很多人找不到

                                                    回復  更多評論
                                                    

                                                  # re: 使用Memory Analyzer tool(MAT)分析內存泄漏(一) 2013-06-16 22:09 woyaowenzi
                                                  第一張圖沒了。  回復  更多評論
                                                    

                                                  # re: 使用Memory Analyzer tool(MAT)分析內存泄漏(一) 2014-04-15 17:46 janeni_s
                                                  很老厲害的博文 膜拜  回復  更多評論
                                                    

                                                  # re: 使用Memory Analyzer tool(MAT)分析內存泄漏(一) 2014-09-17 19:01 chenlian
                                                  我達州人,呵呵  回復  更多評論
                                                    

                                                  # re: 使用Memory Analyzer tool(MAT)分析內存泄漏(一) 2014-09-17 19:01 chenlian
                                                  QQ584314183  回復  更多評論
                                                    

                                                  # re: 使用Memory Analyzer tool(MAT)分析內存泄漏(一) 2014-10-31 16:58 liyghting
                                                  @woyaowenzi看了下源碼,引用的是sun公司的,估計地址換了,就沒有了。  回復  更多評論
                                                    

                                                  # re: 使用Memory Analyzer tool(MAT)分析內存泄漏(一)[未登錄] 2014-12-24 16:31 dd
                                                  @BeanSoft
                                                    回復  更多評論
                                                    

                                                  # re: 使用Memory Analyzer tool(MAT)分析內存泄漏(一)[未登錄] 2015-04-20 15:02 yoyo
                                                  贊一個  回復  更多評論
                                                    

                                                  # re: 使用Memory Analyzer tool(MAT)分析內存泄漏(一) 2015-11-11 15:36 JDongfeng
                                                  好文章,頂一個  回復  更多評論
                                                    

                                                  # re: 使用Memory Analyzer tool(MAT)分析內存泄漏(一) 2016-06-14 11:17 袁良錠
                                                  小瑕疵。
                                                  圖片顯示不了。  回復  更多評論
                                                    


                                                  只有注冊用戶登錄后才能發表評論。


                                                  網站導航:
                                                   
                                                  精准平特三肖
                                                  <nobr id="rub96"><optgroup id="rub96"></optgroup></nobr>

                                                  <bdo id="rub96"></bdo>

                                                    1. <track id="rub96"><div id="rub96"></div></track>
                                                      <nobr id="rub96"><optgroup id="rub96"></optgroup></nobr>

                                                          <nobr id="rub96"><address id="rub96"><big id="rub96"></big></address></nobr>
                                                        1. <menuitem id="rub96"><strong id="rub96"><menu id="rub96"></menu></strong></menuitem>
                                                          <dl id="rub96"><source id="rub96"><tr id="rub96"></tr></source></dl>
                                                          1. <tbody id="rub96"><div id="rub96"></div></tbody>
                                                            1. <bdo id="rub96"><optgroup id="rub96"></optgroup></bdo>
                                                            2. <bdo id="rub96"><dfn id="rub96"><dd id="rub96"></dd></dfn></bdo>
                                                              1. <option id="rub96"><source id="rub96"></source></option>
                                                              2. <bdo id="rub96"></bdo>

                                                                  <p id="rub96"><tr id="rub96"></tr></p>
                                                                1. <tbody id="rub96"></tbody>

                                                                  <bdo id="rub96"></bdo>

                                                                2. <option id="rub96"><source id="rub96"></source></option>

                                                                  <bdo id="rub96"><optgroup id="rub96"><dd id="rub96"></dd></optgroup></bdo>
                                                                    <track id="rub96"></track>

                                                                      <bdo id="rub96"></bdo>
                                                                    1. <option id="rub96"><p id="rub96"><tr id="rub96"></tr></p></option>

                                                                        <bdo id="rub96"></bdo>
                                                                        1. <track id="rub96"></track>
                                                                          1. <track id="rub96"></track>
                                                                                <bdo id="rub96"></bdo>
                                                                                <option id="rub96"></option>

                                                                                    1. <track id="rub96"><span id="rub96"></span></track>

                                                                                        <option id="rub96"></option>

                                                                                        1. 
                                                                                          
                                                                                            <option id="rub96"><span id="rub96"></span></option>
                                                                                            <bdo id="rub96"><address id="rub96"></address></bdo>
                                                                                            <option id="rub96"><source id="rub96"></source></option>
                                                                                              <nobr id="rub96"><address id="rub96"></address></nobr>
                                                                                            1. <nobr id="rub96"><optgroup id="rub96"><big id="rub96"></big></optgroup></nobr>
                                                                                              <track id="rub96"></track>

                                                                                              <nobr id="rub96"><optgroup id="rub96"></optgroup></nobr>
                                                                                                <nobr id="rub96"><optgroup id="rub96"></optgroup></nobr>

                                                                                                <bdo id="rub96"></bdo>

                                                                                                  1. <track id="rub96"><div id="rub96"></div></track>
                                                                                                    <nobr id="rub96"><optgroup id="rub96"></optgroup></nobr>

                                                                                                        <nobr id="rub96"><address id="rub96"><big id="rub96"></big></address></nobr>
                                                                                                      1. <menuitem id="rub96"><strong id="rub96"><menu id="rub96"></menu></strong></menuitem>
                                                                                                        <dl id="rub96"><source id="rub96"><tr id="rub96"></tr></source></dl>
                                                                                                        1. <tbody id="rub96"><div id="rub96"></div></tbody>
                                                                                                          1. <bdo id="rub96"><optgroup id="rub96"></optgroup></bdo>
                                                                                                          2. <bdo id="rub96"><dfn id="rub96"><dd id="rub96"></dd></dfn></bdo>
                                                                                                            1. <option id="rub96"><source id="rub96"></source></option>
                                                                                                            2. <bdo id="rub96"></bdo>

                                                                                                                <p id="rub96"><tr id="rub96"></tr></p>
                                                                                                              1. <tbody id="rub96"></tbody>

                                                                                                                <bdo id="rub96"></bdo>

                                                                                                              2. <option id="rub96"><source id="rub96"></source></option>

                                                                                                                <bdo id="rub96"><optgroup id="rub96"><dd id="rub96"></dd></optgroup></bdo>
                                                                                                                  <track id="rub96"></track>

                                                                                                                    <bdo id="rub96"></bdo>
                                                                                                                  1. <option id="rub96"><p id="rub96"><tr id="rub96"></tr></p></option>

                                                                                                                      <bdo id="rub96"></bdo>
                                                                                                                      1. <track id="rub96"></track>
                                                                                                                        1. <track id="rub96"></track>
                                                                                                                              <bdo id="rub96"></bdo>
                                                                                                                              <option id="rub96"></option>

                                                                                                                                  1. <track id="rub96"><span id="rub96"></span></track>

                                                                                                                                      <option id="rub96"></option>

                                                                                                                                      1. 
                                                                                                                                        
                                                                                                                                          <option id="rub96"><span id="rub96"></span></option>
                                                                                                                                          <bdo id="rub96"><address id="rub96"></address></bdo>
                                                                                                                                          <option id="rub96"><source id="rub96"></source></option>
                                                                                                                                            <nobr id="rub96"><address id="rub96"></address></nobr>
                                                                                                                                          1. <nobr id="rub96"><optgroup id="rub96"><big id="rub96"></big></optgroup></nobr>
                                                                                                                                            <track id="rub96"></track>

                                                                                                                                            <nobr id="rub96"><optgroup id="rub96"></optgroup></nobr>
                                                                                                                                            1. 2013上证指数历史数据 pk10走势图杀码技巧 非全日制研究生 有什么好手艺能赚钱 斗地主游戏基本规则 最准三碼中特三中三 申城棋牌官网 调教女仆游戏手机无敌版 84棋牌娱乐app 永久可用出号公式 彩票网站下载平台登录 京香julia 女优名器 工商注册赚钱吗 湖北十一选五走势图 体彩打票软件 南京小姐兼职