本文是為大家精心整理JVM內存分配、垃圾收集器和常用參數這三方面的知識點,希望大家能熟練掌握好jvm的基礎知識點,為成為優秀的程序猿打下堅實的基礎。
熟練掌握jvm的基礎知識是作為java程序猿必需掌握的,這可以幫助我們:
如java.lang.OutOfMemoryError:Java heap space
java.lang.OutOfMemoryError: GCoverhead limit execeeded
java.lang.OutOfMemoryError: PermGenspace
如對象使用完置null及時GC、慎用System.gc()
盡量不要編寫返回大數據集的方法(如大數據量的接口)
慎用大量jvm級別的緩存
如代碼問題導致頻繁full gc帶來的性能問題
分析內存方法:heap dump 工具:mat

注:JDK1.3.1版本開始使用HotSpot虛擬機
棧區(vm stack)
由編譯器自動分配釋放,存放方法的參數值,局部變量的值等,具體方法執行結束之后,系統自動釋放內存資源。
本地方法棧(nativemethod stack)
與vm stack基本類似,區別在于虛擬機棧為虛擬機執行的java方法服務,而本地方法棧則是為Native方法服務。
靜態區,即方法區(PermSpace)
存放加載的類信息、全局常量、靜態變量、是各個線程共享的內存區域,不回收釋放。
堆區(Heap)
一般由程序員分配釋放,存放由new創建的對象和數組,GC主要操作的對象。
程序計數器
VM執行字節碼指令,分支、循環、異常處理、線程恢復等需要
分代收集策略下的堆(heap)區內存分配

Java堆分為新生代(young區)、老年代(old區)和永久代(Permanent區),新生代(young區)分為伊甸(eden)區和幸存區0(S0)和幸存區1(S1)。
GC有兩種類型:ScavengeGC和Full GC。
ScavengeGC對young區的回收,Eden區被寫滿后觸發;
FullGC對整個堆進行整理回收,一般old區被寫滿后觸發;
Scavenge GC也簡稱YGC,FullGC簡稱FGC,FGC時要鎖內存,FGC太頻繁會大大影響性能。
young區垃圾回收原理:
Eden:對象只管申請空間,是新new對象的樂園。在空間滿的時候,會進行大屠殺(Scavenge GC)
S區:幸存區,在對Eden屠殺時,會把仍然存活的對象拷貝到幸存區。幸存區存在對等的兩個區間,對于一次Scavenge
GC,其中一個為From區,一個為To區。含義為Eden和From的幸存者被拷貝到To區,To區會作為下一次GC的From區
Old: Eden和S區是新生代(young區)的一部分,相對地,在幸存區經歷N次,屠殺后仍然存活的話,會被拷貝到old區,進入old區后,ScavengeGC將不在檢查對象有效性,需要觸發FullGC來回收對象(詳見下圖)。


7種收集器,分為兩塊,上面為新生代收集器,下面是老年代收集器,存在連線兩個收集器可以搭配使用,總的來講分為:串行收集器、并行收集器、并發收集器。
1.Serial(串行GC)收集器
單線程執行,執行時必須暫停其他所有的用戶線程,是Jvm client模式下默認收集器
2.ParNew(并行GC)收集器
是serial收集器的多線程版本
3.ParallelScavenge(并行回收GC)收集器
多線程并行執行。它的目標則是達到一個可控制的吞吐量。吞吐量=程序運行時間/(程序運行時間+垃圾收集時間),如虛擬機總共運行了100分鐘。其中垃圾收集花掉1分鐘,吞吐量則99%。
1.CMS(并發GC)收集器
一種以獲取最短回收停頓時間為目標的收集器。基于“標記-清除”算法實現
2.Serial Old(串行GC)收集器
是Serial收集器的老年代版本,單線程執行,使用“標記-整理”算法。
3.ParallelOld(并行GC)收集器
是Parallel Scavenge收集器的老年代版本,使用多線程和“標記-整理”算法。
4.G1收集器
JDK1.7提供的一個新收集器,基于“標記-整理”算法實現,收集范圍整個Java堆(包括新生代,老年代)。

如果性能要求特別高建議配置使用CMS(并發GC)收集器。

?jvm參數配置示例

附:查看jvm GC情況示例
用java自帶的工具jstat命令查看
命令格式:
jstat [Options] vmid [interval][count]
參數說明:
Options,選項,我們一般使用-gcutil查看gc情況
vmid,VM的進程號,即當前運行的java進程號
interval,間隔時間,單位為秒或者毫秒
count,打印次數,如果缺省則打印無數次
如查看jvm gc的簡單信息
jstat -gcutil 31479 500
即會每500毫秒一次顯示進程號為31479的java進程的GC情況,如下圖:

新聞熱點
疑難解答