要了解Java垃圾收集機(jī)制,,先理解JVM內(nèi)存模式是非常重要的,。今天我們將會(huì)了解JVM內(nèi)存的各個(gè)部分、如何監(jiān)控以及垃圾收集調(diào)優(yōu),。 Java(JVM)內(nèi)存模型 正如你從上面的圖片看到的,,JVM內(nèi)存被分成多個(gè)獨(dú)立的部分。廣泛地說(shuō),,JVM堆內(nèi)存被分為兩部分——年輕代(Young Generation)和老年代(Old Generation),。 年輕代 年輕代是所有新對(duì)象產(chǎn)生的地方,。當(dāng)年輕代內(nèi)存空間被用完時(shí),,就會(huì)觸發(fā)垃圾回收。這個(gè)垃圾回收叫做Minor GC,。年輕代被分為3個(gè)部分——Enden區(qū)和兩個(gè)Survivor區(qū),。 年輕代空間的要點(diǎn):
年老代 年老代內(nèi)存里包含了長(zhǎng)期存活的對(duì)象和經(jīng)過(guò)多次Minor GC后依然存活下來(lái)的對(duì)象,。通常會(huì)在老年代內(nèi)存被占滿時(shí)進(jìn)行垃圾回收。老年代的垃圾收集叫做Major GC,。Major GC會(huì)花費(fèi)更多的時(shí)間,。 Stop the World事件 所有的垃圾收集都是“Stop the World”事件,因?yàn)樗械膽?yīng)用線程都會(huì)停下來(lái)直到操作完成(所以叫“Stop the World”),。 因?yàn)槟贻p代里的對(duì)象都是一些臨時(shí)(short-lived )對(duì)象,,執(zhí)行Minor GC非常快,,所以應(yīng)用不會(huì)受到(“Stop the World”)影響,。 由于Major GC會(huì)檢查所有存活的對(duì)象,因此會(huì)花費(fèi)更長(zhǎng)的時(shí)間,。應(yīng)該盡量減少M(fèi)ajor GC,。因?yàn)镸ajor GC會(huì)在垃圾回收期間讓你的應(yīng)用反應(yīng)遲鈍,所以如果你有一個(gè)需要快速響應(yīng)的應(yīng)用發(fā)生多次Major GC,,你會(huì)看到超時(shí)錯(cuò)誤,。 垃圾回收時(shí)間取決于垃圾回收策略,。這就是為什么有必要去監(jiān)控垃圾收集和對(duì)垃圾收集進(jìn)行調(diào)優(yōu)。從而避免要求快速響應(yīng)的應(yīng)用出現(xiàn)超時(shí)錯(cuò)誤,。 永久代 永久代或者“Perm Gen”包含了JVM需要的應(yīng)用元數(shù)據(jù),,這些元數(shù)據(jù)描述了在應(yīng)用里使用的類和方法。注意,,永久代不是Java堆內(nèi)存的一部分,。 永久代存放JVM運(yùn)行時(shí)使用的類。永久代同樣包含了Java SE庫(kù)的類和方法,。永久代的對(duì)象在full GC時(shí)進(jìn)行垃圾收集,。 方法區(qū) 方法區(qū)是永久代空間的一部分,并用來(lái)存儲(chǔ)類型信息(運(yùn)行時(shí)常量和靜態(tài)變量)和方法代碼和構(gòu)造函數(shù)代碼,。 內(nèi)存池 如果JVM實(shí)現(xiàn)支持,,JVM內(nèi)存管理會(huì)為創(chuàng)建內(nèi)存池,用來(lái)為不變對(duì)象創(chuàng)建對(duì)象池,。字符串池就是內(nèi)存池類型的一個(gè)很好的例子,。內(nèi)存池可以屬于堆或者永久代,這取決于JVM內(nèi)存管理的實(shí)現(xiàn),。 運(yùn)行時(shí)常量池 運(yùn)行時(shí)常量池是每個(gè)類常量池的運(yùn)行時(shí)代表,。它包含了類的運(yùn)行時(shí)常量和靜態(tài)方法。運(yùn)行時(shí)常量池是方法區(qū)的一部分,。 Java棧內(nèi)存 Java棧內(nèi)存用于運(yùn)行線程,。它們包含了方法里的臨時(shí)數(shù)據(jù)、堆里其它對(duì)象引用的特定數(shù)據(jù),。你可以閱讀棧內(nèi)存和堆內(nèi)存的區(qū)別,。 Java 堆內(nèi)存開(kāi)關(guān) Java提供了大量的內(nèi)存開(kāi)關(guān)(參數(shù)),我們可以用它來(lái)設(shè)置內(nèi)存大小和它們的比例,。下面是一些常用的開(kāi)關(guān):
Java垃圾回收大多數(shù)時(shí)候,,上面的選項(xiàng)已經(jīng)足夠使用了。但是如果你還想了解其他的選項(xiàng),,那么請(qǐng)查看JVM選項(xiàng)官方網(wǎng)頁(yè),。 Java垃圾回收會(huì)找出沒(méi)用的對(duì)象,把它從內(nèi)存中移除并釋放出內(nèi)存給以后創(chuàng)建的對(duì)象使用,。Java程序語(yǔ)言中的一個(gè)最大優(yōu)點(diǎn)是自動(dòng)垃圾回收,,不像其他的程序語(yǔ)言那樣需要手動(dòng)分配和釋放內(nèi)存,比如C語(yǔ)言,。 垃圾收集器是一個(gè)后臺(tái)運(yùn)行程序,。它管理著內(nèi)存中的所有對(duì)象并找出沒(méi)被引用的對(duì)象。所有的這些未引用的對(duì)象都會(huì)被刪除,,回收它們的空間并分配給其他對(duì)象,。 一個(gè)基本的垃圾回收過(guò)程涉及三個(gè)步驟:
簡(jiǎn)單標(biāo)記和清除方法存在兩個(gè)問(wèn)題:
上面簡(jiǎn)單清除方法的問(wèn)題在于Java垃圾收集的分代回收的,,而且在堆內(nèi)存里有年輕代和年老代兩個(gè)區(qū)域。我已經(jīng)在上面解釋了Minor GC和Major GC是怎樣掃描對(duì)象,,以及如何把對(duì)象從一個(gè)分代空間移到另外一個(gè)分代空間,。 Java垃圾回收類型 這里有五種可以在應(yīng)用里使用的垃圾回收類型。僅需要使用JVM開(kāi)關(guān)就可以在我們的應(yīng)用里啟用垃圾回收策略,。讓我們一起來(lái)逐一了解:
Java垃圾收集監(jiān)控 我們可以使用命令行和圖形工具來(lái)監(jiān)控監(jiān)控應(yīng)用垃圾回收,。例如,我使用Java SE下載頁(yè)中的一個(gè)demo來(lái)實(shí)驗(yàn),。 如果你想使用同樣的應(yīng)用,,可以到Java SE下載頁(yè)面下載JDK 7和JavaFX演示和示例,。我使用的示例應(yīng)用是Java2Demo.jar,它位于 jdk1.7.0_55/demo/jfc/Java2D 目錄下,。這只是一個(gè)可選步驟,,你可以運(yùn)行GC監(jiān)控命令監(jiān)控任何Java應(yīng)用。 我打開(kāi)演示應(yīng)用使用的命令是:
jsat 可以使用jstat命令行工具監(jiān)控JVM內(nèi)存和垃圾回收,。標(biāo)準(zhǔn)的JDK已經(jīng)附帶了jstat,,所以不需要做任何額外的事情就可以得到它。 要運(yùn)行jstat你需要知道應(yīng)用的進(jìn)程id,,你可以使用 ps -eaf | grep java 命令獲取進(jìn)程id,。
從上面知道,我的Java應(yīng)用進(jìn)程id是9582?,F(xiàn)在可以運(yùn)行jstat命令了,,就像下面展示的一樣:
jstat命令的最后一個(gè)參數(shù)是每個(gè)輸出的時(shí)間間隔。每隔一秒就會(huì)打印出內(nèi)存和垃圾收集數(shù)據(jù),。 讓我們一起來(lái)對(duì)每一列的意義進(jìn)行逐一了解:
jstat的優(yōu)點(diǎn),我們同樣可以在沒(méi)有GUI的遠(yuǎn)程服務(wù)器上運(yùn)行jstat,。注意:我們是通過(guò) -Xmn10m 選項(xiàng)來(lái)指定S0C,、S1C和EC的總和為10m的,。 Java VisualVM及Visual GC插件 如果你想在GUI里查看內(nèi)存和GC,那么可以使用jvisualvm工具,。Java VisualVM同樣是JDK的一部分,,所以你不需要單獨(dú)去下載。 在終端運(yùn)行jvisualvm命令啟動(dòng)Java VisualVM程序,。一旦啟動(dòng)程序,,你需要從Tools->Plugins選項(xiàng)安裝Visual GC插件,就像下面圖片展示的,。 安裝完Visual GC插件后,,從左邊欄打開(kāi)應(yīng)用并把視角轉(zhuǎn)到Visual GC部分。你將會(huì)得到關(guān)于JVM內(nèi)存和垃圾收集詳情,,如下圖所示,。 Java垃圾回收調(diào)優(yōu) Java垃圾回收調(diào)優(yōu)應(yīng)該是提升應(yīng)用吞吐量的最后一個(gè)選擇。在你發(fā)現(xiàn)應(yīng)用由于長(zhǎng)時(shí)間垃圾回收導(dǎo)致了應(yīng)用性能下降,、出現(xiàn)超時(shí)的時(shí)候,,應(yīng)該考慮Java垃圾收集調(diào)優(yōu)。 如果你在日志里看到 java.lang.OutOfMemoryError: PermGen space錯(cuò)誤,,那么可以嘗試使用 -XX:PermGen 和 -XX:MaxPermGen JVM選項(xiàng)去監(jiān)控并增加Perm Gen內(nèi)存空間,。你也可以嘗試使用-XX:+CMSClassUnloadingEnabled并查看使用CMS垃圾收集器的執(zhí)行性能。 如果你看到了大量的Full GC操作,,那么你應(yīng)該嘗試增大老年代的內(nèi)存空間,。 全面垃圾收集調(diào)優(yōu)要花費(fèi)大量的努力和時(shí)間,這里沒(méi)有一塵不變的硬性調(diào)優(yōu)規(guī)則,。你需要去嘗試不同的選項(xiàng)并且對(duì)這些選項(xiàng)進(jìn)行對(duì)比,,從而找出最適合自己應(yīng)用的方案。 這就是所有的Java內(nèi)存模型和垃圾回收內(nèi)容,。希望對(duì)你理解JVM內(nèi)存和垃圾收集過(guò)程有所幫助,。 原文鏈接: journaldev 翻譯: ImportNew.com - 進(jìn)林 譯文鏈接: http://www./14086.html
|
|