運維必會JVM知識

Java的GC機制

回收的對象:不存在任何引用的對象

堆區(qū)(Heap)

堆區(qū)是GC最頻繁的,也是理解GC機制最重要的區(qū)域笼痹。堆區(qū)由所有線程共享配喳,在虛擬機啟動時創(chuàng)建。堆區(qū)主要用于存放對象實例及數(shù)組凳干,所有new出來的對象都存儲在該區(qū)域界逛。

如何判斷對象是垃圾 ?

引用計數(shù)算法
經典的引用計數(shù)算法,每個對象添加到引用計數(shù)器纺座,每被引用一次,計數(shù)器+1溉潭,失去引用净响,計數(shù)器-1,當計數(shù)器在一段時間內為0時喳瓣,即認為該對象可以被回收了馋贤。但是這個算法有個明顯的缺陷:當兩個對象相互引用,但是二者都已經沒有作用時畏陕,理應把它們都回收配乓,但是由于它們相互引用,不符合垃圾回收的條件,所以就導致無法處理掉這一塊內存區(qū)域犹芹。因此崎页,Sun的JVM并沒有采用這種算法,而是采用一個叫——根搜索算法腰埂,如圖:

image

根搜索算法

基本思想是:從一個叫GC Roots的根節(jié)點出發(fā)飒焦,向下搜索,如果一個對象不能達到GC Roots的時候屿笼,說明該對象不再被引用牺荠,可以被回收。如上圖中的Object5驴一、Object6休雌、Object7,雖然它們三個依然相互引用肝断,但是它們其實已經沒有作用了杈曲,這樣就解決了引用計數(shù)算法的缺陷。

內存分代

JVM區(qū)域總體分兩類孝情,heap區(qū)和非heap區(qū)鱼蝉。
heap區(qū)又分為:

Eden Space(伊甸園)、

對象被創(chuàng)建的時候首先放到這個區(qū)域箫荡,進行垃圾回收后魁亦,不能被回收的對象被放入到空的survivor區(qū)域

Survivor Space(幸存者區(qū))、

用于保存在eden space內存區(qū)域中經過垃圾回收后沒有被回收的對象

回收的時候Eden區(qū)域不能被回收的對象被放入到空的survivor(也就是To Survivor羔挡,同時Eden區(qū)域的內存會在垃圾回收的過程中全部釋放)洁奈,
另一個survivor(即From Survivor)里不能被回收的對象也會被放入這個survivor(即To Survivor),然后To Survivor 和 From Survivor的標記會互換绞灼,始終保證一個survivor是空的利术,涉及到一個算法

Eden SpaceSurvivor Space都屬于新生代,新生代中執(zhí)行的垃圾回收被稱之為Minor GC(因為是對新生代進行垃圾回收低矮,所以又被稱為Young GC)印叁,每一次Young GC后留下來的對象age加1

新生代進行垃圾回收時會出發(fā)Minor GC(也稱作Young GC

Old Gen(老年代)。

非heap區(qū)又分:

Code Cache(代碼緩存區(qū))军掂;
Perm Gen(永久代)轮蜕;

(Perm Gen全稱是Permanent Generation space,是指內存的永久保存區(qū)域)
Jvm Stack(java虛擬機棧)蝗锥;
默認大小為物理內存的1/64跃洛。
不會被JVM垃圾回收

老年代用于存放新生代多次回收依然存活的對象,如緩存對象终议。老年代滿了的時候就需要對老年代進行回收汇竭,老年代的垃圾回收稱作Major GC(也稱作Full GC
永久代是有大小限制的葱蝗,因此如果加載的類太多,很有可能導致永久代內存溢出

Local Method Statck(本地方法棧)细燎;

垃圾回收器

1.串行收集
2.并行收集
3.CMS收集器
4.G1收集器

使用G1收集器時两曼,Java堆的內存布局與其他收集器有很大差別,它將整個Java堆劃分為多個大小相等的獨立區(qū)域(Region)找颓,雖然還保留有新生代和老年代的概念合愈,但新生代和老年代不再是物理隔閡了,它們都是一部分(可以不連續(xù))Region的集合击狮。

GC常見算法佛析?

1.復制算法
2.標記--清除算法
3.標記--壓縮算法
4.分代回收算法

JVM參數(shù)調優(yōu)

image.png

注:jdk8 開始,用 MetaSpace (元空間)區(qū)取代了 Perm 區(qū)(永久代)彪蓬,所以相應的 jvm 參數(shù)變成 -XX:MetaspaceSize 及 -XX:MaxMetaspaceSize寸莫。

MetaSpace GC

如果Metaspace的空間占用達到了設定的最大值,那么就會觸發(fā)GC來收集死亡對象和類的加載器档冬。根據(jù)JDK 8的特性膘茎,G1和CMS都會很好地收集Metaspace區(qū)(一般都伴隨著Full GC)。

為了減少垃圾回收的頻率及時間酷誓,控制吞吐量披坏,對Metaspace進行適當?shù)谋O(jiān)控和調優(yōu)是非常有必要的。如果在Metaspace區(qū)發(fā)生了頻繁的Full GC盐数,那么可能表示存在內存泄露或Metaspace區(qū)的空間太小了棒拂。

新增的 JVM 參數(shù)

-XX:MetaspaceSize 是分配給類元數(shù)據(jù)空間(以字節(jié)計)的初始大小(Oracle邏輯存儲上的初始高水位,the initial high-water-mark )玫氢,此值為估計值帚屉。MetaspaceSize的值設置的過大會延長垃圾回收時間。垃圾回收過后漾峡,引起下一次垃圾回收的類元數(shù)據(jù)空間的大小可能會變大攻旦。

-XX:MaxMetaspaceSize 是分配給類元數(shù)據(jù)空間的最大值,超過此值就會觸發(fā)Full GC生逸,此值默認沒有限制牢屋,但應取決于系統(tǒng)內存的大小。JVM會動態(tài)地改變此值槽袄。

-XX:MinMetaspaceFreeRatio 表示一次GC以后伟阔,為了避免增加元數(shù)據(jù)空間的大小,空閑的類元數(shù)據(jù)的容量的最小比例掰伸,不夠就會導致垃圾回收。

-XX:MaxMetaspaceFreeRatio 表示一次GC以后怀估,為了避免增加元數(shù)據(jù)空間的大小狮鸭,空閑的類元數(shù)據(jù)的容量的最大比例合搅,不夠就會導致垃圾回收。

JVM參數(shù)優(yōu)化
image.png

調優(yōu)原則

調優(yōu)方法以及原則一切都是為了這一步歧蕉,調優(yōu)灾部,在調優(yōu)之前,我們需要記住下面的原則:

1惯退、多數(shù)的Java應用不需要在服務器上進行GC優(yōu)化赌髓;
2、多數(shù)導致GC問題的Java應用催跪,都不是因為我們參數(shù)設置錯誤锁蠕,而是代碼問題;
3懊蒸、在應用上線之前荣倾,先考慮將機器的JVM參數(shù)設置到最優(yōu)(最適合);
4骑丸、減少創(chuàng)建對象的數(shù)量舌仍;
5、減少使用全局變量和大對象通危;
6铸豁、GC優(yōu)化是到最后不得已才采用的手段;
7菊碟、在實際使用中节芥,分析GC情況優(yōu)化代碼比優(yōu)化GC參數(shù)要多得多;

Java虛擬機參數(shù)設置:
(1)性能參數(shù):

-server

以server模式運行時將擁有:更大框沟、更高的并發(fā)處理能力藏古,更快更強捷的JVM垃圾回收機制,可以獲得更多的負載與吞吐量

-Xmx
  指定java程序的最大堆內存, 使用java -Xmx5000M -version判斷當前系統(tǒng)能分配的最大堆內存

-Xms
  指定最小堆內存, 通常設置成跟最大堆內存一樣忍燥,減少GC

-Xmn
  設置年輕代大小為512m拧晕。整個堆大小=年輕代大小 + 年老代大小。所以增大年輕代后梅垄,將會減小年老代大小厂捞。此值對系統(tǒng)性能影響較大,Sun官方推薦配置為整個堆的3/8队丝。

-Xss
  指定線程的最大椕夷伲空間, 此參數(shù)決定了java函數(shù)調用的深度, 值越大調用深度越深, 若值太小則容易出棧溢出錯誤(StackOverflowError)
設定每個線程的堆棧大小。這個就要依據(jù)你的程序机久,看一個線程 大約需要占用多少內存臭墨,可能會有多少線程同時運行等。一般不易設置超過1M膘盖,要不然容易出現(xiàn)out ofmemory

-XX:PermSize
  指定方法區(qū)(永久區(qū))的初始值,默認是物理內存的1/64胧弛, 在Java8永久區(qū)移除, 代之的是元數(shù)據(jù)區(qū)尤误, 由-XX:MetaspaceSize指定

-XX:MaxPermSize
  指定方法區(qū)的最大值, 默認是物理內存的1/4, 在java8中由-XX:MaxMetaspaceSize指定元數(shù)據(jù)區(qū)的大小

-XX:NewRatio=n
  年老代與年輕代的比值结缚,-XX:NewRatio=2, 表示年老代與年輕代的比值為2:1

-XX:SurvivorRatio=n
  Eden區(qū)與Survivor區(qū)的大小比值损晤,-XX:SurvivorRatio=8表示Eden區(qū)與Survivor區(qū)的大小比值是8:1:1,因為Survivor區(qū)有兩個(from, to)

-XX:+DoEscapeAnalysis
  開啟逃逸分析, 逃逸分析的目的是判斷對象的作用域是否可能逃逸出函數(shù)體, 逃逸分析是棧上分配的技術基礎红竭,對于非逃逸對象而言就是一個局部變量, 而對象未發(fā)生逃逸時, 虛擬機就有可能進行線上分配, 不是堆上, 棧上分配速度快尤勋,并且能避免垃圾回收帶來的負面影響, 棧上分配是虛擬機提供的很好的對象分配優(yōu)化策略

-XX:+EliminateAllocations
  開啟標量替換(默認打開), 即允許對象打散分配在棧上, 即對象的屬性視為獨立局部變量進行分配到棧上

-XX:+UseCompressedOops
  開啟指針壓縮

-XX:+AggressiveOpts
  啟用JVM開發(fā)團隊最新的調優(yōu)成果。例如編譯優(yōu)化茵宪,偏向鎖最冰,并行年老代收集等

-XX:-UseTLAB
  關閉TLAB , 默認是打開的

-Djava.awt.headless=true
  有時我們會在我們的J2EE工程中使用一些圖表工具如:jfreechart,用于在web網頁輸出GIF/JPG等流眉厨,在winodws環(huán)境下锌奴,一般我 們的app server在輸出圖形時不會碰到什么問題,但是在linux/unix環(huán)境下經常會碰到一個exception導致你在winodws開發(fā)環(huán)境下圖片顯 示的好好可是在linux/unix下卻顯示不出來憾股,因此加上這個參數(shù)以免避這樣的情況出現(xiàn).

-XX:+DisableExplicitGC
  在程序代碼中不允許有顯示的調用”System.gc()”鹿蜀。看到過有兩個極品工程中每次在DAO操作結束時手動調用System.gc()一下服球,覺得這 樣做好像能夠解決它們的out ofmemory問題一樣罕拂,付出的代價就是系統(tǒng)響應時間嚴重降低枫笛,就和我在關于Xms,Xmx里的解釋的原理一樣民宿,這樣去調用GC導致系統(tǒng)的JVM大起大 落进胯,性能不到什么地方去喲!

-XX:+UseBiasedLocking
  偏向鎖粉渠,啟用一個優(yōu)化了的線程鎖分冈,我們知道在我們的appserver,每個http請求就是一個線程霸株,有的請求短有的請求長雕沉,就會有請求排隊的現(xiàn)象,甚至還會出現(xiàn)線程阻塞去件,這個優(yōu)化了的線程鎖使得你的appserver內對線程處理自動進行最優(yōu)調配坡椒。

GC策略

策略 1:將新對象預留在新生代,由于 Full GC 的成本遠高于 Minor GC尤溜,因此盡可能將對象分配在新生代是明智的做法倔叼,實際項目中根據(jù) GC 日志分析新生代空間大小分配是否合理,適當通過“-Xmn”命令調節(jié)新生代大小宫莱,最大限度降低新對象直接進入老年代的情況丈攒。

策略 2:大對象進入老年代,雖然大部分情況下,將對象分配在新生代是合理的巡验。但是對于大對象這種做法卻值得商榷识椰,大對象如果首次在新生代分配可能會出現(xiàn)空間不足導致很多年齡不夠的小對象被分配的老年代,破壞新生代的對象結構深碱,可能會出現(xiàn)頻繁的 full gc。因此藏畅,對于大對象敷硅,可以設置直接進入老年代(當然短命的大對象對于垃圾回收老說簡直就是噩夢)。-XX:PretenureSizeThreshold 可以設置直接進入老年代的對象大小愉阎。

策略 3:合理設置進入老年代對象的年齡绞蹦,-XX:MaxTenuringThreshold 設置對象進入老年代的年齡大小,減少老年代的內存占用榜旦,降低 full gc 發(fā)生的頻率幽七。

策略 4:設置穩(wěn)定的堆大小,堆大小設置有兩個參數(shù):-Xms 初始化堆大小溅呢,-Xmx 最大堆大小澡屡。

策略5:注意:如果滿足下面的指標,則一般不需要進行 GC 優(yōu)化:

MinorGC 執(zhí)行時間不到50ms咐旧;

Minor GC 執(zhí)行不頻繁驶鹉,約10秒一次;

Full GC 執(zhí)行時間不到1s铣墨;

Full GC 執(zhí)行頻率不算頻繁室埋,不低于10分鐘1次。

監(jiān)控JVM

一伊约,需求:大數(shù)據(jù)的機器姚淆,很多jvm進程,需要監(jiān)控特定的幾個的進程的FGC,FGCT,YGC,YGCT,GCT屡律。

YGC:從應用程序啟動到采樣時年輕代中gc次數(shù)
YGCT:從應用程序啟動到采樣時年輕代中gc所用時間(s)
FGC:從應用程序啟動到采樣時old代(全gc)gc次數(shù)
FGCT:從應用程序啟動到采樣時old代(全gc)gc所用時間(s)
GCT:從應用程序啟動到采樣時gc用的總時間(s)

二 編寫自定義監(jiān)控項腳步

jps命令可以獲取到進程的ID腌逢,jstat -gc ID ,獲取gc的信息
參數(shù)詳解
jstat參考

cat jps1.py
#!/usr/bin/env python
import os,sys

jps_info = os.popen("/usr/bin/sudo /usr/local/java/bin/jps | grep %s | awk '{print $1}'"% sys.argv[1])
jps_info = jps_info.read()
jps_id = jps_info.strip()

jstat = {'YGC':'$13','YGCT':'$14','FGC':'$15','FGCT':'$16','GCT':'$17'}

info = jstat[sys.argv[2]]
command = "/usr/bin/sudo /usr/local/java/bin/jstat -gc "+jps_id+" | awk '{print "+info+"}'| /usr/bin/tail -n 1"

os.system(command)

三疹尾,編輯zabbix agent配置文件

添加:UserParameter=jstat[*], /usr/bin/python /etc/zabbix/scripts/jps1.py $1 $2

四上忍,其它地方的調整

在本機測試腳本是正常的,但是在zabbix server上測試有幾個問題需要修改

編輯 /etc/sudoers文件纳本,添加一行:

  zabbix    ALL=(ALL)       NOPASSWD:ALL

  這一行需要注釋掉:#Defaults    requiretty  

五窍蓝,創(chuàng)建監(jiān)控項(數(shù)據(jù)類型選擇浮點數(shù))

image

六,添加模板展示

image

如何修改JVM參數(shù)

在安裝目錄的bin/catalina.sh 文件的cygwin=false上面加上:

JAVA_OPTS="-Xms256m -Xmx2048m -XX:PermSize=128m -XX:MaxPermSize=512m"
或者
CATALINA_OPTS="-Xms256m -Xmx2048m -XX:PermSize=128m -XX:MaxPermSize=512m"

參考:
https://www.sczyh30.com/posts/Java/jvm-metaspace/
http://www.reibang.com/p/bc2e4d4ff018

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市繁成,隨后出現(xiàn)的幾起案子吓笙,更是在濱河造成了極大的恐慌,老刑警劉巖巾腕,帶你破解...
    沈念sama閱讀 216,402評論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件面睛,死亡現(xiàn)場離奇詭異絮蒿,居然都是意外死亡,警方通過查閱死者的電腦和手機叁鉴,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評論 3 392
  • 文/潘曉璐 我一進店門土涝,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人幌墓,你說我怎么就攤上這事但壮。” “怎么了常侣?”我有些...
    開封第一講書人閱讀 162,483評論 0 353
  • 文/不壞的土叔 我叫張陵蜡饵,是天一觀的道長。 經常有香客問我胳施,道長溯祸,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,165評論 1 292
  • 正文 為了忘掉前任舞肆,我火速辦了婚禮焦辅,結果婚禮上,老公的妹妹穿的比我還像新娘胆绊。我一直安慰自己氨鹏,他們只是感情好,可當我...
    茶點故事閱讀 67,176評論 6 388
  • 文/花漫 我一把揭開白布压状。 她就那樣靜靜地躺著仆抵,像睡著了一般。 火紅的嫁衣襯著肌膚如雪种冬。 梳的紋絲不亂的頭發(fā)上镣丑,一...
    開封第一講書人閱讀 51,146評論 1 297
  • 那天,我揣著相機與錄音娱两,去河邊找鬼莺匠。 笑死,一個胖子當著我的面吹牛十兢,可吹牛的內容都是我干的趣竣。 我是一名探鬼主播,決...
    沈念sama閱讀 40,032評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼旱物,長吁一口氣:“原來是場噩夢啊……” “哼遥缕!你這毒婦竟也來了?” 一聲冷哼從身側響起宵呛,我...
    開封第一講書人閱讀 38,896評論 0 274
  • 序言:老撾萬榮一對情侶失蹤单匣,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體户秤,經...
    沈念sama閱讀 45,311評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡码秉,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,536評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了鸡号。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片转砖。...
    茶點故事閱讀 39,696評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖鲸伴,靈堂內的尸體忽然破棺而出堪藐,到底是詐尸還是另有隱情,我是刑警寧澤挑围,帶...
    沈念sama閱讀 35,413評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站糖荒,受9級特大地震影響杉辙,放射性物質發(fā)生泄漏。R本人自食惡果不足惜捶朵,卻給世界環(huán)境...
    茶點故事閱讀 41,008評論 3 325
  • 文/蒙蒙 一蜘矢、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧综看,春花似錦品腹、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至析珊,卻和暖如春羡鸥,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背忠寻。 一陣腳步聲響...
    開封第一講書人閱讀 32,815評論 1 269
  • 我被黑心中介騙來泰國打工惧浴, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人奕剃。 一個月前我還...
    沈念sama閱讀 47,698評論 2 368
  • 正文 我出身青樓衷旅,卻偏偏與公主長得像,于是被迫代替她去往敵國和親纵朋。 傳聞我的和親對象是個殘疾皇子柿顶,可洞房花燭夜當晚...
    茶點故事閱讀 44,592評論 2 353

推薦閱讀更多精彩內容

  • Java 虛擬機有自己完善的硬件架構, 如處理器、堆棧倡蝙、寄存器等九串,還具有相應的指令系統(tǒng)。JVM 屏蔽了與具體操作系...
    尹小凱閱讀 1,687評論 0 10
  • 轉載blog.csdn.net/ning109314/article/details/10411495/ JVM工...
    forever_smile閱讀 5,366評論 1 56
  • JVM架構 當一個程序啟動之前,它的class會被類裝載器裝入方法區(qū)(Permanent區(qū))猪钮,執(zhí)行引擎讀取方法區(qū)的...
    cocohaifang閱讀 1,664評論 0 7
  • 內存溢出和內存泄漏的區(qū)別 內存溢出:out of memory品山,是指程序在申請內存時,沒有足夠的內存空間供其使用烤低,...
    Aimerwhy閱讀 741評論 0 1
  • GC區(qū)域Eden Survivor(from,to), Old Gen和Perm Gen VM區(qū)域總體分兩類肘交,he...
    Fitz_Lee閱讀 415評論 0 0