太長不看版 這篇文章講了啥
線上機器cpu使用率突然飙升 怎麼辦?
線上機器頻繁full GC 怎麼辦?
oom怎麼預防 難道隻有事故發生了才知道麼?平時怎麼防患于未然?
指引
先放一張圖

沒錯 我們的老朋友arthas。神器阿爾薩斯。下午剛剛在伺服器部署好的,感覺非常興奮,又有了新玩具(hahhh)。
當然如果沒有阿爾薩斯也沒關系。這篇文章會比較入門向。涉及到以下一些點
怎麼觀察線上heap狀态。所謂防患于未然。之前介紹過jmap和jstats,現在會更進一步講下怎麼看懂這些名額。
線上cpu突然飙升怎麼定位問題。涉及到一點點jvm的配置。所謂的調優。
之前的文章提過一些:
怎麼用阿爾薩斯排除線上bug
OOM的排除過程
1: 怎麼防患于未然--觀察heap名額
主要是觀察%CPU和%MEM。通俗易懂。
程序名額:
GC名額:
GC需要了解一些背景知識,才能看懂名額。
1:堆記憶體
我們的堆實體記憶體是這樣配置設定的。【本文的jdk 1.8。預設垃圾回收器ParallelGC套裝。】
JAVA的所有配置設定在堆上的對象會首先在eden區上占用一塊地方。伊甸園是人類祖先生活的地方,約等于人類出生的地方。eden區(伊甸區)可以大緻認為是對象(指配置設定在堆上的對象)出生的地方。比如說 A a = new A()。new字元會向jvm申請一個記憶體空間,這個記憶體空間會用來存放剛出生的對象baby,這個房子擁有一個像0x2222211這樣16進制的值來标記它在jvm中的實體實際位址(類似于我家住西北旺東路10号院東區21号樓這種)。這個房子就在伊甸區中。
JVM通過根可達算法知道每一個對象的實體位址。每一個對象都住在一個小房子裡。JVM管理了一大片房子,像下面這樣的,每一個小格子就是一個房子,房子裡住着一個對象。
通過根可達算法計算知道還住人的房子是灰色的格子【存活對象】。還沒有住人的房子是綠色的格子【未使用】。曾經住過人,但是現在人去樓空的房子是黑色的格子【可回收】。黑色的格子就是重點關注對象。我們需要清除掉它們【清除掉不用的東西,又叫垃圾回收】,才能保證新的人來的時候有房子住【記憶體可以為新對象建立新空間】。
在清理的過程中,由于伊甸區的人很多是新來的,他們不穩定,很快就搬走了。會出現非常多的人去樓空的黑色格子。為了非常快的清理他們的痕迹,讓他們曾經住的房子能夠很快被弄好給新的人住。jvm發明了一種方法:每次清理【垃圾回收】的時候,把所有還生活在這個小區的人,就是綠色格子,遷移去隔壁的小區【s區】。現在,這個小區就沒活人住了,jvm轟一下把它炸平【直接扔掉】,然後砰砰砰再在原址上重新修一個新的【新的eden區】。這樣,新的對象出生就又可以住伊甸區了。這個方法有個名字叫copying,是3種基礎的垃圾回收算法之一。
之後,沒有多久,伊甸區再次出現了非常多的人去樓空的房子。第二次清理【垃圾回收】的過程開始了。這次, jvm會把伊甸區還生活的人和之前遷移過一次到s0還生活的人一起遷移到s0右邊的另外一個小區s1。然後轟一下把伊甸區和s0全部炸平。然後砰砰砰再在原址上重新修一個新的伊甸區和s0。第二次垃圾回收完成。
之後。人去樓空。第三次清理【垃圾回收】。轟。砰砰砰。s1和edean被炸平。人去了s0。 接着,轟,砰砰砰。
轟,砰砰。
直到s區和伊甸區沒有能住下新的人的房子了,這個時候會觸發ygc。伊甸區和s區合稱新生代,ygc全稱young gc。簡單說就是把大家都轟,然後再把大家都砰砰砰。值得一提的是,某些在年輕代經曆過比較多次清理還倔強生活在這裡的人,會獲得jvm的respect,搬到隔壁的老年代,又叫終身區。這個多次到底是多少次呢。是可以配置在jvm的參數中的。cms是6次,其他9種垃圾回收器都是15次。當老年區生活的人越來越多,直到有一天老年區也沒有能住下新的人的房子了,這個時候就會觸發fgc。fgc全稱full gc。簡單說就是把大家都轟,然後再砰砰砰。
總結一下啊: eden//s0//s1: 合稱年輕代 住的地方 不大的小區。 tenure(old): 老年代 住的地方 大的小區 ygc: young gc 年輕代空間耗盡時觸發 fgc: full gc 老年代空間耗盡時觸發。年輕代和老年代同時進行回收。
2:觀察gc ---- jstat
NGC: 目前的年輕代記憶體約168m
NGMX: 最大的年輕代約524m (mn代表最小 不解釋)
S0C: S0區無對象
S1C: S1區約50m
EC: 伊甸區約166m (不知道為什麼NGC<S+EDEN)
OGC: 老年代目前約352m
YGC: 年輕代垃圾回收發生41266次
FGC: 老年代垃圾回收發生14次
N: 目前的年輕代記憶體約168m
S0: S0區無對象
S1: S1使用100%
E: 伊甸區使用54.07%
O: 老年代使用85.51%
YGC: 年輕代垃圾回收發生41329次
YGCT: 年輕代垃圾回收耗時1187.704ms
FGCT: 老年代垃圾回收耗時18.581ms
GCT: 垃圾回收總耗時 1206.285ms
3:觀察gc ---- jmap
4: 觀察gc ---- 無敵的阿爾薩斯 我最常用的是dashboard//jvm//thread//watch//trace。但其實是阿爾薩斯有非常多的用法,可以自行移步Arthas官方文檔。阿裡,java的神。
2: 線上cpu突然飙升怎麼辦
····
怎麼辦?
先重新開機啊 。
網管。加5塊錢,拿個泡面。
我是嚴肅的分割線。
2: 線上cpu突然飙升怎麼辦 之定位問題
首先,最重要的一點是用剛剛教的指令找出占用最多的對象和線程。尤其是線程。
線程分為業務線程和垃圾回收兩種。如果是前者,那麼很簡單。arthas找到線程号,然後通過線程号去找到堆棧資訊。根據堆棧資訊定位到是哪一句話出問題。記憶體占用直接去看是不是循環或者無邊界隊列/鍊建立了太多不可以被垃圾回收的對象。基本上不會差太多。下面這兩種寫法,大家自己揣摩一下。
這裡提一些記憶體洩漏和記憶體溢出的差别。
記憶體洩漏: 指不可以被根可達算法抵達的對象。沒有引用卻也無法回收。釘子戶。
内容溢出: 實體空間被占滿了。新對象無法申請新記憶體空間。
回到線程類型的問題上來。如果是垃圾回收線程占用空間。一般思路就是去查對象。jamp -dump分析dump檔案。分析軟體找到最大占用的對象的調用鍊,搞明白它們是怎麼被建立出來卻又不能被回收的。線程池,連接配接池,或者各種queue。懂得都懂。
我給大家畫了一個圖,獻醜了:
制作非常精良,一看就是長期有調優經驗的人才能看懂的。
聽懂掌聲。