華爲二面:你真的明白Java垃圾回收器嗎?我用這份筆記狂懟面試官

{"type":"doc","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#1F1F1F","name":"user"}}],"text":"今日分享開始啦,請大家多多指教~","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"第一階段:串行垃圾回收器:jdk1.3.1之前Java虛擬機僅僅只支持Serial收集器。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"第二階段:並行垃圾回收器:隨着多核的出現,Java引入了並行垃圾回收器,充分利用多核性能提升垃圾回收效率。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"第三階段:併發標記清理回收器CMS:垃圾回收器可以和應用程序同時運行,降低暫停用戶線程執行的時間。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"第四階段:G1(併發)回收器:初衷是在清理非常大的堆空間的時候能滿足特定的暫停應用程序的時間,與CMS相比會有更少的內存碎片。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","text":"1 垃圾回收算法","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","text":"1-1 標記清除算法","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"算法概述","attrs":{}}]},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"優點:回收速度快","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"缺點:造成內存碎片,無法分配大的連續空間。","attrs":{}}]}]}],"attrs":{}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"算法思想","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在Java9之前,Java默認使用的垃圾回收器是ParallelGC,從Java9開始G1作爲了默認的垃圾回收器","attrs":{}}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/77/774e93ca69506937befeb06e5032ae28.png","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#4D4D4D","name":"user"}}],"text":"step1: 第一次掃描,通過GC root對象判斷堆內存中哪些對象可以進行垃圾回收,進行標記。","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#4D4D4D","name":"user"}}],"text":"step2: 第二次掃描, 將那些標記的GC root對象進行垃圾回收,只需要將起始內存地址與終止內存地址放入空閒內存區就行。","attrs":{}}]}]}],"attrs":{}},{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","text":"1-2 標記整理算法","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"第一個依舊是標記,第二步會進行一個空間整理,從而不產生碎片。","attrs":{}}]},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"優點:避免了內存碎片","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"缺點:對空間的整理使得效率比較低下。","attrs":{}}]}]}],"attrs":{}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/57/57424464eca3ce6c210d502efbdc34cf.png","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","text":"1-3 複製算法","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"特點:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"將管理的內存分爲2塊區域,from區域與to區域,將那些不需要回收的對象從from區域拷貝到to區域。複製的過程中完成內存區域的整理。之後交換from和to的指向。","attrs":{}}]},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"優點:不會產生內存碎片","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"缺點:需要雙倍的內存空間,內存利用率不高,而且拷貝也需要時間。","attrs":{}}]}]}],"attrs":{}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/0e/0e4c3777fe17a1a5de6d4c846f9eae0d.jpeg","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/17/17eaf612a62e4dc3cdb5f784c36ed042.png","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/a2/a234cee09b8f49ede0e9467244a9516d.png","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","text":"1-4 三種垃圾回收算法總結","attrs":{}}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/03/03ff6ade827d73ec2845d74b12e06aac.png","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"注意:實際的JVM垃圾回收算法中上面的三種算法是綜合使用的。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","text":"2 JVM分代回收算法","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","text":"2-1 概述","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Garden of Eden:伊甸園 garbage:垃圾","attrs":{}}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/cf/cf5df329adce9056f5dabd49b95566f0.png","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"新生代主要由三部分內容組成,分別是Eden區,倖存區from,倖存區to。 通常情況下只有Eden區與倖存區from會存放數目,倖存區to只有垃圾回收時,複製對象會用到。堆內存的新生代進行一次垃圾回收(Minor GC),大部分對象都會都會被回收。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"老年代通常存放一些經常被使用的對象,一個對象如果經歷多次垃圾回收仍然倖存,那麼該對象會從新生代放入老年代。只有新生代內存不足並且老年代內存也不足的時候纔會觸發full GC對老年代的對象進行垃圾回收。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"爲什麼需要進行劃分?","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"實際環境中,對象的生命週期是不同的,老年代的對象生命週期比較長,可能很長時間才進行一次垃圾回收。新生代的對象生命週期比較短,垃圾回收比較頻繁。這種分區法方便採用不同的垃圾回收算法更加有效地進行垃圾回收。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","text":"2-2 分代垃圾回收示例","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"step1:程序剛剛開始運行,產生的對象先放入Eden區,當Eden區放不下的時候。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"step2:對Eden區進行Minor GC,並將沒有被垃圾回收的對象複製的倖存區To,然後交換倖存區To和倖存區From,第一次垃圾回收的最終的效果如下圖所示:","attrs":{}}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/dc/dcf72d3e955a916a234b5e904bf3d6cf.png","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"step3: 第一次Minor GC, Eden區又有空間可以分配給新的對象使用,經過一段時間Eden又不夠用了,觸發第二次Minor GC, 這次垃圾會檢查Eden區以及倖存區From哪些對象可以存活,並將這些對象複製到倖存區To,然後交換倖存區To和倖存區From,這個時候Eden區又空了出來,可以放置新的對象。","attrs":{}}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/04/0410c73456124fa6b110b6bdf707b115.png","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#4D4D4D","name":"user"}}],"text":"實際垃圾回收過程中,JVM會對每個對象經過垃圾回收倖存下來的次數進行記錄,比如上圖中,倖存區的2個對象經過垃圾回收的次數分別是1和2。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#4D4D4D","name":"user"}}],"text":"step4: 當一些對象經過垃圾回收的次數仍然倖存的次數達到一個閾值(說明這個對象價值比較高),那麼這個對象會被移動到老年代。","attrs":{}}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/ab/ab74d9b259abe1b90fa11f59dde16d5c.png","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#4D4D4D","name":"user"}}],"text":"極端情況考慮:Eden區,from區,老年區都已經滿了?","attrs":{}}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/26/269866ee936e4572ea032ccc917c93ee.png","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"此時會觸發Full GC(優先Minor GC,Minor GC依舊內存不夠)","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","text":"2-3 分代垃圾回收的總結","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"對象首先分配在伊甸園區域","attrs":{}}]},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"新生代空間不足時,觸發 minor gc,伊甸園和 from 存活的對象使用 copy複製到 to 中,存活的對象年齡加1並且交換from to。","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"minor gc 會引發stop the world,暫停其它用戶的線程,等垃圾回收結束,用戶線程才恢復運行暫停時間較短,由於新生代大部分對象都是垃圾,複製的對象很少,所以效率較高。","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"當對象壽命超過閾值時,會晉升至老年代,最大壽命是15(4bit,對象頭存儲)。","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"當老年代空間不足,會先嚐試觸發 minor gc,如果之後空間仍不足,那麼觸發full gc,STW的時間更長。","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Full GC 的stop the world的時間要比MInor GC時間長,老年代存活對象較多加上空間整理時間,所以停止時間會較長。如果Full GC後,空間仍然不足會觸發內存不足的異常。","attrs":{}}]}]}],"attrs":{}},{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","text":"2-4 垃圾回收相關的虛擬機參數","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"垃圾回收器概述","attrs":{}}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/84/846a9bd3b58986e0055dc4e26b12c050.png","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","text":"2-5 垃圾回收案例分析","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"情況1:什麼都不放的情況","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"new generation:新生代 tenured generation:老年代","attrs":{}}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/ed/ed127c44bb4a6f6e982823b943bcc9d4.png","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#4D4D4D","name":"user"}}],"text":"情況1執行結果","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#4D4D4D","name":"user"}}],"text":"可以看到即使用戶沒有創建對象,系統對象也要佔據一部分堆內存空間。","attrs":{}}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/34/3409c99ad993a7ef818f66c66fd707fb.png","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#4D4D4D","name":"user"}}],"text":"Java的內存對象都是分配在堆上嗎","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#4D4D4D","name":"user"}},{"type":"strong","attrs":{}}],"text":"情況2:新生代堆空間放滿,觸發GC","attrs":{}}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/9b/9b10b68a992cdc328afb4f3d2f3cb4a7.png","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#4D4D4D","name":"user"}}],"text":"情況2執行結果","attrs":{}}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/4c/4ca283758150d1b65a98c05e5d326ef1.png","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#4D4D4D","name":"user"}},{"type":"strong","attrs":{}}],"text":"情況3: 新生代內存隨着對象的增多放不下了","attrs":{}}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/3d/3d48fc8c67300db66f9557be4e1908b6.png","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#4D4D4D","name":"user"}}],"text":"執行結果","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#4D4D4D","name":"user"}}],"text":"新生代放不下,將新生代的對象放置到老年代。","attrs":{}}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/96/965bf9113d4eeac842654936f717c951.png","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#4D4D4D","name":"user"}},{"type":"strong","attrs":{}}],"text":"情況4:一開始直接分配大於新生代的內存,如果老年代放得下,則直接放到老年代","attrs":{}}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/3a/3adca0487aa8279b04f5a85709263299.png","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#4D4D4D","name":"user"}}],"text":"執行結果","attrs":{}}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/08/08bee309f2d0a18aed70c7b0410694da.png","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#4D4D4D","name":"user"}}],"text":"當內存比較緊張的時候,即新生代內存放不下的時候,有時候會直接將對象分配到老年代,或者直接在回收次數較少(未達到15次)的情況下,直接將新生代對象弄到老年代。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","text":"2 垃圾回收器","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","text":"2-1 垃圾回收器概述","attrs":{}}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/f9/f94034a2d323072a34510f60f72843e2.png","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#4D4D4D","name":"user"}}],"text":"CMS垃圾回收器後來被G1垃圾回收器取代。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","text":"2-2 串行垃圾回收器","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"開啓串行垃圾回收器的JVM參數","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"-XX:+UseSerialGC = Serial + SerialOld","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"// Serial:工作在新生代,採用複製的垃圾回收算法","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"// SerialOld:工作在老生代,採用標記+整理的垃圾回收算法","attrs":{}}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/95/9546c346c1bbd63cd9f2ac3453e4765e.png","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"總結:觸發垃圾回收時,讓多個線程在一個安全點停下來,然後使用單線程的垃圾回收器去進行垃圾回收,垃圾回收完成後,再讓其他線程運行。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","text":"2-3 吞吐量優先的垃圾回收器","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"開啓吞吐量優先的垃圾回收器的JVM參數","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"開啓/關閉的參數","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"默認的多線程垃圾回收器,前者是開啓新生代回收器,採用複製算法,後者是開啓老年代回收器,採用標記+拷貝算法。下面選項只要開啓一個,那麼另外一個也會開啓。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"-XX:+UseParallelGC , -XX:+UseParallelOldGC","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#4D4D4D","name":"user"}}],"text":"開啓自適應動態調整新生代的大小,晉升閾值","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"-XX:+UseAdaptiveSizePolicy","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"二個指標調整的參數(ParallelGC會根據設定的指標去調整堆的大小到達下面期望設定的目標)","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"指標1)1/(1+ratio) = 垃圾回收的時間/總的運行時間","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"ratio默認值時99,即垃圾回收的時間不超過總時間1%。但一般設爲19。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如果達不到目標,ParallelGC會調整堆內存大小來達到這個目標,通常是調大,這樣垃圾回收的次數會減少,從而提高吞吐量","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"-XX:GCTimeRatio=ratio","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#4D4D4D","name":"user"}}],"text":"指標2)每次垃圾回收的時間限制( 最大暫停的毫秒數)","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#4D4D4D","name":"user"}}],"text":"默認值是200ms顯然將堆內存空間變小有助於減少每次垃圾回收的時間","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"-XX:MaxGCPauseMillis=ms","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"總結:顯然指標1)與指標2)是有衝突的。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"-XX:ParallelGCThreads=n //垃圾回收並行的線程數目","attrs":{}}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/ad/ad69042762f777c9eb3c3f15da1d0050.png","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"總結:採用多線程方式進行垃圾回收,垃圾回收的線程數目通常根據CPU的核數進行設置。在垃圾回收階段,並行的垃圾回收線程會充分佔用CPU。在非垃圾回收階段,用戶線程會充分利用CPU資源。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","text":"2-4 響應時間優先的垃圾回收器(CMS垃圾回收器)","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"缺點:採用的標記清除算法產生內存碎片需要退化成單線程的垃圾整理回收器,造成響應時間變長。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"開啓的JVM參數","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"注意這個是併發的採用標記清除算法的垃圾回收,這裏區別於之前的垃圾回收器,該垃圾回收器能夠在進行垃圾回收的同時運行其他非垃圾回收線程(也存在時間階段需要停止,但不是所有階段停止)。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"老年代併發的垃圾回收器會出現失敗的情況,這時老年代垃圾回收器會退化成單線程的垃圾回收器(SerialOld)","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"-XX:+UseConcMarkSweepGC // use concurrent mark sweep(會產生垃圾碎片) 工作在老年代的垃圾回收器","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"-XX:+UseParNewGC // 工作在新生代的垃圾回收器","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#4D4D4D","name":"user"}},{"type":"strong","attrs":{}}],"text":"重要的初始參數","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"-XX:ParallelGCThreads=n // 並行的垃圾回收線程數,通常等於CPU的核心數(垃圾回收並行階段)","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"-XX:ConcGCThreads=threads // 併發的線程數目,通常設爲並行垃圾回收線程數的1/4(垃圾回收併發階段)","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#4D4D4D","name":"user"}},{"type":"strong","attrs":{}}],"text":"其他參數","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"-XX:CMSInitiatingOccupancyFraction=percent // 執行垃圾回收的內存佔比,預留空間給浮動垃圾","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"-XX:+CMSScavengeBeforeRemark","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"// 在重新標記前,對新生代進行垃圾回收,減少併發清理的垃圾對象,+開啓,-關閉","attrs":{}}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/79/79999ef016fe3c0c52e125c666650a6a.png","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"浮動垃圾是指併發清理過程中用戶線程新產生的垃圾,需要等待下次併發清理。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"併發工作流程概述:","attrs":{}}]},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"step1:老年代發生內存不存的現象。","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"step2:ConcMarkSweepGC會進行一個初始標記動作(初始標記需要STW即阻塞非垃圾回收線程),初始標記只標記根對象,所以速度非常快,暫停時間也非常短。","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"step3:完成初始標記後,之前阻塞的線程又可以運行了,這個時候垃圾回收線程進行併發標記。","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"step4:併發標記結束後,需要再次阻塞非垃圾回收線程,進行一個所謂的重新標記,","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"step5:重新標記完成後,阻塞的線程又可以運行了。垃圾回收線程也併發的清理垃圾對象。","attrs":{}}]}]}],"attrs":{}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"總結:初始標記與重新標記需要阻塞線程。 在併發階段,由於垃圾回收線程佔用資源,所以系統的吞吐量會受到一定的影響,但是系統的響應速度由於併發執行不會受到垃圾回收的明顯影響(相比較其他垃圾回收器,STW時間只需要進行初始標記與重新標記,並且能夠不阻塞其他線程進行垃圾的標記與清除)。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#1F1F1F","name":"user"}}],"text":"今日份分享已結束,請大家多多包涵和指點!","attrs":{}}]}]}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章