這篇文章是我之前翻閱了不少的書籍以及從網(wǎng)絡(luò)上收集的一些資料的整理回窘,因此不免有一些不準確的地方冯挎,同時不同JDK版本的差異也比較大泉瞻。
5.垃圾回收
5.1 按代實現(xiàn)垃圾回收
新生代(Young generation):
絕大多數(shù)最新被創(chuàng)建的對象會被分配到這里系吭,由于大部分對象在創(chuàng)建后會很快變得不可到達五嫂,所以很多對象被創(chuàng)建在新生代,然后消失肯尺。對象從這個區(qū)域消失的過程我們稱之為”minor GC“沃缘。
新生代中存在一個Eden區(qū)和兩個Survivor區(qū)。新對象會首先分配在 Eden 中(如果新對象過大则吟,會直接分配在老年代中)槐臀。在GC中,Eden 中的對象會被移動到survivor中氓仲,直至對象滿足一定的年紀(定義為熬過GC的次數(shù)),會被移動到老年代(具體細節(jié)將在下邊垃圾收集算法中討論)水慨。
可以設(shè)置新生代和老年代的相對大小得糜。這種方式的優(yōu)點是新生代大小會隨著整個堆大小動態(tài)擴展。參數(shù) -XX:NewRatio 設(shè)置老年代與新生代的比例晰洒。例如 -XX:NewRatio=8 指定老年代/新生代為8/1. 老年代占堆大小的 7/8 朝抖,新生代占 1/8 .(默認即使1/8)
例如:-XX:NewSize=64m -XX:MaxNewSize=1024m -XX:NewRatio=8
老年代(Old generation):
對象沒有變得不可達,并且從新生代中存活下來欢顷,會被拷貝到這里槽棍。其所占用的空間要比新生代多。也正由于其相對較大的空間抬驴,發(fā)生在老年代上的GC要比新生代少得多炼七。對象從老年代中消失的過程,可以稱之為”major GC“(或者”full GC“)
永久代(permanent generation):
像一些類的層級信息布持,方法數(shù)據(jù)和方法信息(如字節(jié)碼豌拙,棧和變量大小)题暖,運行時常量池(jdk7之后移出永久代)按傅,已確定的符號引用和虛方法表等等,它們幾乎都是靜態(tài)的并且很少被卸載和回收胧卤,在JDK8之前的HotSpot虛擬機中唯绍,類的這些“永久的”數(shù)據(jù)存放在一個叫做永久代的區(qū)域。永久代一段連續(xù)的內(nèi)存空間枝誊,我們在JVM啟動之前可以通過設(shè)置-XX:MaxPermSize的值來控制永久代的大小况芒。但是jdk8之后取消了永久代,這些元數(shù)據(jù)被移到了一個與堆不相連的本地內(nèi)存區(qū)域 叶撒。
5.2 怎樣判斷對象是否已經(jīng)死亡
引用計數(shù)收集算法
用計數(shù)是垃圾收集器中的早期策略绝骚。在這種方法中,堆中每個對象(不是引用)都有一個引用計數(shù)祠够。當一個對象被創(chuàng)建時压汪,且將該對象分配給一個變量,該變量計數(shù)設(shè)置為1古瓤。當任何其它變量被賦值為這個對象的引用時止剖,計數(shù)加1(a = b,則b引用的對象+1),但當一個對象的某個引用超過了生命周期或者被設(shè)置為一個新值時落君,對象的引用計數(shù)減1穿香。任何引用計數(shù)為0的對象可以被當作垃圾收集。當一個對象被垃圾收集時叽奥,它引用的任何對象計數(shù)減1。
- 優(yōu)點:引用計數(shù)收集器可以很快的執(zhí)行痛侍,交織在程序運行中朝氓。對程序不被長時間打斷的實時環(huán)境比較有利魔市。
- 缺點: 無法檢測出循環(huán)引用。如父對象有一個對子對象的引用赵哲,子對象反過來引用父對象待德。這樣,他們的引用計數(shù)永遠不可能為0.
可達性分析算法
通過一系列稱為”GC Roots”的對象作為起點枫夺,從這些節(jié)點開始向下搜索将宪,搜索所有走過的路徑稱為引用鏈,當一個對象到GC Roots沒有任何引用鏈相連時(從GC Roots到此對象不可達)橡庞,則證明此對象是不可用的较坛。
可作為GC Roots的對象包括:
- 虛擬機棧中所引用的對象(本地變量表)
- 方法區(qū)中類靜態(tài)屬性引用的對象
- 方法區(qū)中常量引用的對象
- 本地方法棧中JNI引用的對象(Native對象)
5.3 java中的引用
強引用(Strong Reference):
在代碼中普遍存在的,類似”O(jiān)bject obj = new Object”這類引用扒最,只要強引用還在丑勤,垃圾收集器永遠不會回收掉被引用的對象
軟引用(Sofe Reference):
有用但并非必須的對象,可用SoftReference類來實現(xiàn)軟引用吧趣,在系統(tǒng)將要發(fā)生內(nèi)存溢出異常之前法竞,將會把這些對象列進回收范圍之中進行二次回收。如果這次回收還沒有足夠的內(nèi)存强挫,才會拋出內(nèi)存異常異常岔霸。
弱引用(Weak Reference):
被弱引用關(guān)聯(lián)的對象只能生存到下一次垃圾收集發(fā)生之前,JDK提供了WeakReference類來實現(xiàn)弱引用俯渤。
虛引用(Phantom Reference):
也稱為幽靈引用或幻影引用呆细,是最弱的一種引用關(guān)系,JDK提供了PhantomReference類來實現(xiàn)虛引用稠诲。
5.4 finalize方法什么作用
對于一個對象來說侦鹏,在被判斷沒有 GCroots 與其相關(guān)聯(lián)時,被第一次標記臀叙,然后判斷該對象是否應(yīng)該執(zhí)行finalize方法(判斷依據(jù):如果對象的finalize方法被復(fù)寫略水,并且沒有執(zhí)行過,則可以被執(zhí)行)劝萤。如果允許執(zhí)行那么這個對象將會被放到一個叫F-Query的隊列中渊涝,等待被執(zhí)行。(注意:由于finalize的優(yōu)先級比較低床嫌,所以該對象的的finalize方法不一定被執(zhí)行跨释,即使被執(zhí)行了,也不保證finalize方法一定會執(zhí)行完)
5.5 垃圾收集算法
標記-清除算法:
標記-清除算法采用從根集合進行掃描厌处,對存活的對象進行標記鳖谈,標記完畢后,再掃描整個空間中未被標記的對象阔涉,進行回收缆娃。標記-清除算法不需要進行對象的移動捷绒,并且僅對不存活的對象進行處理,在存活對象比較多的情況下極為高效贯要,但由于標記-清除算法直接回收不存活的對象暖侨,因此會造成內(nèi)存碎片。
復(fù)制算法:
這種收集算法將堆棧分為兩個域崇渗,常稱為半空間字逗。每次僅使用一半的空間,JVM生成的新對象則放在另一半空間中宅广。GC運行時葫掉,它把可到達對象復(fù)制到另一半空間,從而壓縮了堆棧乘碑。這種方法適用于短生存期的對象挖息,持續(xù)復(fù)制長生存期的對象則導(dǎo)致效率降低。并且對于指定大小堆來說兽肤,需要兩倍大小的內(nèi)存套腹,因為任何時候都只使用其中的一半。
標記整理算法:
標記-整理算法采用標記-清除算法一樣的方式進行對象的標記资铡,但在清除時不同电禀,在回收不存活的對象占用的空間后,會將所有的存活對象往一端空閑空間移動笤休,并更新對應(yīng)的指針尖飞。標記-整理算法是在標記-清除算法的基礎(chǔ)上,又進行了對象的移動店雅,因此成本更高政基,但是卻解決了內(nèi)存碎片的問題。
分代收集算法:
在上邊三種收集思想中加入了分代的思想闹啦。
5.6 Hotspot實現(xiàn)垃圾回收細節(jié)
一致性:
在可達性分析期間整個系統(tǒng)看起來就像被凍結(jié)在某個時間點上沮明,不可以出現(xiàn)分析過程中對象引用關(guān)系還在不斷變化的情況。
一致性要求導(dǎo)致GC進行時必須停頓所有Java執(zhí)行線程窍奋。(Stop The World)即使在號稱不會發(fā)生停頓的CMS收集器中荐健,枚舉根節(jié)點時也是必須停頓的。
HotSpot使用的是準確式GC琳袄,當執(zhí)行系統(tǒng)停頓下來后江场,并不需要一個不漏地檢查完所有執(zhí)行上下文和全局的引用位置,這是通過一組稱為OopMap的數(shù)據(jù)結(jié)構(gòu)來達到的窖逗。
安全點(Safe Point):
程序只有在到達安全點時才能暫停址否。安全點的選定標準是“是否具有讓程序長時間執(zhí)行的特征”∷槲桑“長時間執(zhí)行”的最明顯特征就是指令序列的復(fù)用佑附,如方法調(diào)用用含、循環(huán)跳轉(zhuǎn)等,具有這些功能的指令才會產(chǎn)生安全點帮匾。
讓程序暫停的兩種方式:
* 搶先式中斷(Preemptive Suspension):在GC發(fā)生時,主動中斷所有線程痴鳄,不需要線程執(zhí)行的代碼主動配合瘟斜。如果發(fā)現(xiàn)有線程中斷的地方不在安全點上,就恢復(fù)線程讓它跑到安全點上痪寻。(不推薦)
* 主動式中斷(Voluntary Suspension):設(shè)一個標志螺句,各個線程主動去輪詢這個標志,遇到中斷則暫停橡类。輪詢地方與安全點重合蛇尚。
5.7 垃圾收集器
HotSpot中幾種常見的垃圾收集器:
5.7.1 Serial收集器
Serial收集器是最基本、發(fā)展歷史最悠久的收集器顾画,曾經(jīng)(在JDK 1.3.1之前)是虛擬機新生代收集的唯一選擇取劫。
特性:
這個收集器是一個單線程的收集器,但它的“單線程”的意義并不僅僅說明它只會使用一個CPU或一條收集線程去完成垃圾收集工作研侣,更重要的是在它進行垃圾收集時谱邪,必須暫停其他所有的工作線程,直到它收集結(jié)束庶诡。Stop The World
應(yīng)用場景:
Serial收集器是虛擬機運行在Client模式下的默認新生代收集器惦银。
優(yōu)勢:
簡單而高效(與其他收集器的單線程比),對于限定單個CPU的環(huán)境來說末誓,Serial收集器由于沒有線程交互的開銷扯俱,專心做垃圾收集自然可以獲得最高的單線程收集效率。
5.7.2 ParNew收集器
特性:
ParNew收集器其實就是Serial收集器的多線程版本喇澡,除了使用多條線程進行垃圾收集之外迅栅,其余行為包括Serial收集器可用的所有控制參數(shù)、收集算法撩幽、Stop The World库继、對象分配規(guī)則、回收策略等都與Serial收集器完全一樣窜醉,在實現(xiàn)上宪萄,這兩種收集器也共用了相當多的代碼。
應(yīng)用場景:
ParNew收集器是許多運行在Server模式下的虛擬機中首選的新生代收集器榨惰。有一個很重要的原因是除了Serial收集器外拜英,目前只有它能與CMS收集器配合工作。
Serial收集器 VS ParNew收集器:
ParNew收集器在單CPU的環(huán)境中絕對不會有比Serial收集器更好的效果琅催,甚至由于存在線程交互的開銷居凶,該收集器在通過超線程技術(shù)實現(xiàn)的兩個CPU的環(huán)境中都不能百分之百地保證可以超越Serial收集器虫给。然而,隨著可以使用的CPU的數(shù)量的增加侠碧,它對于GC時系統(tǒng)資源的有效利用還是很有好處的抹估。
5.7.3 Parallel Scavenge收集器
特性:
Parallel Scavenge收集器是一個新生代收集器,它也是使用復(fù)制算法的收集器弄兜,又是并行的多線程收集器药蜻。
應(yīng)用場景:
停頓時間越短就越適合需要與用戶交互的程序,良好的響應(yīng)速度能提升用戶體驗替饿,而高吞吐量則可以高效率地利用CPU時間语泽,盡快完成程序的運算任務(wù),主要適合在后臺運算而不需要太多交互的任務(wù)视卢。
對比分析:
Parallel Scavenge收集器 VS CMS等收集器:
Parallel Scavenge收集器的特點是它的關(guān)注點與其他收集器不同踱卵,CMS等收集器的關(guān) 注點是盡可能地縮短垃圾收集時用戶線程的停頓時間,而Parallel Scavenge收集器的目標則是達到一個可控制的吞吐量(Throughput)据过。
由于與吞吐量關(guān)系密切惋砂,Parallel Scavenge收集器也經(jīng)常稱為“吞吐量優(yōu)先”收集器。
Parallel Scavenge收集器 VS ParNew收集器:
Parallel Scavenge收集器與ParNew收集器的一個重要區(qū)別是它具有自適應(yīng)調(diào)節(jié)策略绳锅。
GC自適應(yīng)的調(diào)節(jié)策略:
Parallel Scavenge收集器有一個參數(shù)-XX:+UseAdaptiveSizePolicy班利。當這個參數(shù)打開之后,就不需要手工指定新生代的大小榨呆、Eden與Survivor區(qū)的比例罗标、晉升老年代對象年齡等細節(jié)參數(shù)了,虛擬機會根據(jù)當前系統(tǒng)的運行情況收集性能監(jiān)控信息积蜻,動態(tài)調(diào)整這些參數(shù)以提供最合適的停頓時間或者最大的吞吐量闯割,這種調(diào)節(jié)方式稱為GC自適應(yīng)的調(diào)節(jié)策略(GC Ergonomics)。
5.7.4 Serial Old收集器
特性:
Serial Old是Serial收集器的老年代版本竿拆,它同樣是一個單線程收集器宙拉,使用標記-整理算法。
應(yīng)用場景:
- Client模式:Serial Old收集器的主要意義也是在于給Client模式下的虛擬機使用丙笋。
- Server模式:如果在Server模式下谢澈,那么它主要還有兩大用途:一種用途是在JDK 1.5以及之前的版本中與Parallel Scavenge收集器搭配使用,另一種用途就是作為CMS收集器的后備預(yù)案御板,在并發(fā)收集發(fā)生Concurrent Mode Failure時使用锥忿。
5.7.5 Parallel Old收集器
特性:
Parallel Old是Parallel Scavenge收集器的老年代版本,使用多線程和“標記-整理”算法怠肋。
應(yīng)用場景:
在注重吞吐量以及CPU資源敏感的場合敬鬓,都可以優(yōu)先考慮Parallel Scavenge加Parallel Old收集器。
這個收集器是在JDK 1.6中才開始提供的,在此之前钉答,新生代的Parallel Scavenge收集器一直處于比較尷尬的狀態(tài)础芍。原因是,如果新生代選擇了Parallel Scavenge收集器数尿,老年代除了Serial Old收集器外別無選擇(Parallel Scavenge收集器無法與CMS收集器配合工作)仑性。由于老年代Serial Old收集器在服務(wù)端應(yīng)用性能上的“拖累”,使用了Parallel Scavenge收集器也未必能在整體應(yīng)用上獲得吞吐量最大化的效果右蹦,由于單線程的老年代收集中無法充分利用服務(wù)器多CPU的處理能力虏缸,在老年代很大而且硬件比較高級的環(huán)境中,這種組合的吞吐量甚至還不一定有ParNew加CMS的組合“給力”嫩实。直到Parallel Old收集器出現(xiàn)后,“吞吐量優(yōu)先”收集器終于有了比較名副其實的應(yīng)用組合窥岩。
5.7.6 CMS收集器
特性:
CMS(Concurrent Mark Sweep)收集器是一種以獲取最短回收停頓時間為目標的收集器甲献。目前很大一部分的Java應(yīng)用集中在互聯(lián)網(wǎng)站或者B/S系統(tǒng)的服務(wù)端上,這類應(yīng)用尤其重視服務(wù)的響應(yīng)速度颂翼,希望系統(tǒng)停頓時間最短晃洒,以給用戶帶來較好的體驗。CMS收集器就非常符合這類應(yīng)用的需求朦乏。
CMS收集器是基于“標記—清除”算法實現(xiàn)的球及,它的運作過程相對于前面幾種收集器來說更復(fù)雜一些,整個過程分為4個步驟:
- 初始標記(CMS initial mark):初始標記僅僅只是標記一下GC Roots能直接關(guān)聯(lián)到的對象呻疹,速度很快吃引,需要“Stop The World”。
- 并發(fā)標記(CMS concurrent mark):并發(fā)標記階段就是進行GC Roots Tracing的過程刽锤。
- 重新標記(CMS remark):重新標記階段是為了修正并發(fā)標記期間因用戶程序繼續(xù)運作而導(dǎo)致標記產(chǎn)生變動的那一部分對象的標記記錄镊尺,這個階段的停頓時間一般會比初始標記階段稍長一些,但遠比并發(fā)標記的時間短并思,仍然需要“Stop The World”庐氮。
- 并發(fā)清除(CMS concurrent sweep):并發(fā)清除階段會清除對象。
由于整個過程中耗時最長的并發(fā)標記和并發(fā)清除過程收集器線程都可以與用戶線程一起工作宋彼,所以弄砍,從總體上來說,CMS收集器的內(nèi)存回收過程是與用戶線程一起并發(fā)執(zhí)行的输涕。
優(yōu)點:
CMS是一款優(yōu)秀的收集器音婶,它的主要優(yōu)點在名字上已經(jīng)體現(xiàn)出來了:并發(fā)收集、低停頓莱坎。
缺點:
-
1)CMS收集器對CPU資源非常敏感
其實桃熄,面向并發(fā)設(shè)計的程序都對CPU資源比較敏感。在并發(fā)階段,它雖然不會導(dǎo)致用戶線程停頓瞳收,但是會因為占用了一部分線程(或者說CPU資源)而導(dǎo)致應(yīng)用程序變慢碉京,總吞吐量會降低。
CMS默認啟動的回收線程數(shù)是(CPU數(shù)量+3)/ 4螟深,也就是當CPU在4個以上時谐宙,并發(fā)回收時垃圾收集線程不少于25%的CPU資源,并且隨著CPU數(shù)量的增加而下降界弧。但是當CPU不足4個(譬如2個)時凡蜻,CMS對用戶程序的影響就可能變得很大。
-
2)CMS收集器無法處理浮動垃圾
CMS收集器無法處理浮動垃圾垢箕,可能出現(xiàn)“Concurrent Mode Failure”失敗而導(dǎo)致另一次Full GC的產(chǎn)生划栓。
由于CMS并發(fā)清理階段用戶線程還在運行著,伴隨程序運行自然就還會有新的垃圾不斷產(chǎn)生条获,這一部分垃圾出現(xiàn)在標記過程之后忠荞,CMS無法在當次收集中處理掉它們,只好留待下一次GC時再清理掉帅掘。這一部分垃圾就稱為“浮動垃圾”委煤。
也是由于在垃圾收集階段用戶線程還需要運行,那也就還需要預(yù)留有足夠的內(nèi)存空間給用戶線程使用修档,因此CMS收集器不能像其他收集器那樣等到老年代幾乎完全被填滿了再進行收集碧绞,需要預(yù)留一部分空間提供并發(fā)收集時的程序運作使用。要是CMS運行期間預(yù)留的內(nèi)存無法滿足程序需要吱窝,就會出現(xiàn)一次“Concurrent Mode Failure”失敗讥邻,這時虛擬機將啟動后備預(yù)案:臨時啟用Serial Old收集器來重新進行老年代的垃圾收集,這樣停頓時間就很長了院峡。
-
3)CMS收集器會產(chǎn)生大量空間碎片
CMS是一款基于“標記—清除”算法實現(xiàn)的收集器计维,這意味著收集結(jié)束時會有大量空間碎片產(chǎn)生∷河瑁空間碎片過多時鲫惶,將會給大對象分配帶來很大麻煩,往往會出現(xiàn)老年代還有很大空間剩余实抡,但是無法找到足夠大的連續(xù)空間來分配當前對象欠母,不得不提前觸發(fā)一次Full GC。
5.7.7 G1收集器
特性:
G1(Garbage-First)是一款面向服務(wù)端應(yīng)用的垃圾收集器吆寨。HotSpot開發(fā)團隊賦予它的使命是未來可以替換掉JDK 1.5中發(fā)布的CMS收集器赏淌。與其他GC收集器相比,G1具備如下特點啄清。
-
1)并行與并發(fā)
G1能充分利用多CPU六水、多核環(huán)境下的硬件優(yōu)勢,使用多個CPU來縮短Stop-The-World停頓的時間,部分其他收集器原本需要停頓Java線程執(zhí)行的GC動作掷贾,G1收集器仍然可以通過并發(fā)的方式讓Java程序繼續(xù)執(zhí)行睛榄。
-
2)分代收集
與其他收集器一樣,分代概念在G1中依然得以保留想帅。雖然G1可以不需要其他收集器配合就能獨立管理整個GC堆场靴,但它能夠采用不同的方式去處理新創(chuàng)建的對象和已經(jīng)存活了一段時間、熬過多次GC的舊對象以獲取更好的收集效果港准。
-
3)空間整合
與CMS的“標記—清理”算法不同旨剥,G1從整體來看是基于“標記—整理”算法實現(xiàn)的收集器,從局部(兩個Region之間)上來看是基于“復(fù)制”算法實現(xiàn)的浅缸,但無論如何轨帜,這兩種算法都意味著G1運作期間不會產(chǎn)生內(nèi)存空間碎片,收集后能提供規(guī)整的可用內(nèi)存衩椒。這種特性有利于程序長時間運行蚌父,分配大對象時不會因為無法找到連續(xù)內(nèi)存空間而提前觸發(fā)下一次GC。
-
4)可預(yù)測的停頓
這是G1相對于CMS的另一大優(yōu)勢烟具,降低停頓時間是G1和CMS共同的關(guān)注點,但G1除了追求低停頓外奠蹬,還能建立可預(yù)測的停頓時間模型朝聋,能讓使用者明確指定在一個長度為M毫秒的時間片段內(nèi),消耗在垃圾收集上的時間不得超過N毫秒囤躁。
在G1之前的其他收集器進行收集的范圍都是整個新生代或者老年代冀痕,而G1不再是這樣。使用G1收集器時狸演,Java堆的內(nèi)存布局就與其他收集器有很大差別言蛇,它將整個Java堆劃分為多個大小相等的獨立區(qū)域(Region),雖然還保留有新生代和老年代的概念宵距,但新生代和老年代不再是物理隔離的了腊尚,它們都是一部分Region(不需要連續(xù))的集合。
G1收集器之所以能建立可預(yù)測的停頓時間模型满哪,是因為它可以有計劃地避免在整個Java堆中進行全區(qū)域的垃圾收集婿斥。G1跟蹤各個Region里面的垃圾堆積的價值大小(回收所獲得的空間大小以及回收所需時間的經(jīng)驗值)哨鸭,在后臺維護一個優(yōu)先列表民宿,每次根據(jù)允許的收集時間,優(yōu)先回收價值最大的Region(這也就是Garbage-First名稱的來由)像鸡。這種使用Region劃分內(nèi)存空間以及有優(yōu)先級的區(qū)域回收方式活鹰,保證了G1收集器在有限的時間內(nèi)可以獲取盡可能高的收集效率。
執(zhí)行過程:
G1收集器的運作大致可劃分為以下幾個步驟:
- 1)初始標記(Initial Marking):初始標記階段僅僅只是標記一下GC Roots能直接關(guān)聯(lián)到的對象,并且修改TAMS(Next Top at Mark Start)的值志群,讓下一階段用戶程序并發(fā)運行時着绷,能在正確可用的Region中創(chuàng)建新對象,這階段需要停頓線程赖舟,但耗時很短蓬戚。
- 2)并發(fā)標記(Concurrent Marking):并發(fā)標記階段是從GC Root開始對堆中對象進行可達性分析,找出存活的對象宾抓,這階段耗時較長子漩,但可與用戶程序并發(fā)執(zhí)行。
- 3)最終標記(Final Marking):最終標記階段是為了修正在并發(fā)標記期間因用戶程序繼續(xù)運作而導(dǎo)致標記產(chǎn)生變動的那一部分標記記錄石洗,虛擬機將這段時間對象變化記錄在線程Remembered Set Logs里面幢泼,最終標記階段需要把Remembered Set Logs的數(shù)據(jù)合并到Remembered Set中,這階段需要停頓線程讲衫,但是可并行執(zhí)行缕棵。
- 4)篩選回收(Live Data Counting and Evacuation):篩選回收階段首先對各個Region的回收價值和成本進行排序,根據(jù)用戶所期望的GC停頓時間來制定回收計劃涉兽,這個階段其實也可以做到與用戶程序一起并發(fā)執(zhí)行招驴,但是因為只回收一部分Region,時間是用戶可控制的枷畏,而且停頓用戶線程將大幅提高收集效率别厘。
何時會拋出OutOfMemoryException,并不是內(nèi)存被耗空的時候才拋出
* JVM98%的時間都花費在內(nèi)存回收
* 每次回收的內(nèi)存小于2%
個人介紹:
高廣超 :多年一線互聯(lián)網(wǎng)研發(fā)與架構(gòu)設(shè)計經(jīng)驗拥诡,擅長設(shè)計與落地高可用触趴、高性能互聯(lián)網(wǎng)架構(gòu)。
本文首發(fā)在 http://www.reibang.com/u/2766e4cfc391)轉(zhuǎn)載請注明渴肉!