天天看點

jvm

目錄

jvm

堆結構

垃圾回收

堆空間

tomcat而言

+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- 張賀,多年網際網路行業工作經驗,擔任過網絡工程師、系統內建工程師、linux系統運維工程師 個人網站:www.zhanghehe.cn

接上一篇部落格,這裡面我們來讨論一下java虛拟機,也就是jvm,在這裡面我們主要關注其垃圾回收機制。

java的核心組成部分有class和執行引擎兩部分組成,當執行引擎執行代碼的時候,會從記憶體裡面開辟出一段空間,這段記憶體區,大體由以下幾個部分組成,如下圖,這幾部分有的是線程之間共享的,有的是獨占的。

下面這圖是jvm的核心組成部分,在關其中的介紹我在上一篇部落格已經說過了,連結在此:

jvm

下文主要是來介紹一個jvm當中的堆,堆是java預留的一段空間,用來存放類執行之後生成的對象,我們知道java不同于c,c需要程式員自己計算記憶體空間,而java是“垃圾回收器”統一回收,回收的主要内容其實就是堆占用的空間,因為堆空間裡面的對象可能調用一次就以後再也不用了,堆空間是最占記憶體的,而且堆是共享的,回收的時候是分代回收,有“年青代”,有“老年代”。

堆的結構如下所示:

jvm

堆内置的記憶體區域分為:

新生代(有垃圾回收機制)

老年代、有垃圾回收機制)

持久代、(沒有垃圾回收機制)

新生代區域又分為:

eden(取自伊旬園,初始之意,執行對象的初始地,相當于新手村)

from(過了新手村之後,就會到達from區域,相當于第一階段,又稱ss1,可類比為少年時期)

to (過了第二階段之後,會到達第三階段,相當于第二階段,又稱ss2,可類比為中年時間)

note:我們注意到在新生代當中還有reserved區域,這個區域是預留的區域,至于它的作用,我們後面會介紹的。

老年代區域又分為(老年代比較簡單,敖過了中年時期才會到達老年代):

老年代空間

預留區域

持久代區域又分為(注意,持久代當中沒有垃圾回收機制,熬過了老年代才會到達持久代):

持久代空間

對象移動過程:

對象剛出生的時候在新生代的eden區域,有的對象用完就不再用了,那麼這個對象就在目前空間原地等待垃圾回收 。

如果這個對象在後面還會用一陣子,這個對象就會移動到from區域

如果這個對象在後面還會再用一陣子,這個對象就會由from移動到to區域

然後下次移動到老年代,最後移動到持久代

垃圾回收頻率和算法:

無論是新生代還是老年代,都會有垃圾回收機制,隻是回收的頻率不一樣,old次數更少,而且算法也不一樣。

無論做什麼事情,在初始階段放棄的人總是非常多,能熬過入門階段就很少有人放棄了。

新生代的垃圾回收算法是minor gc,也被稱之為小gc。

老年代的垃圾回收算法是major gc,也被稱之為full gc或大gc。

垃圾回收的注意點:

垃圾回收不是實時進行的,而是的攢一會再進行的。

垃圾回收的時候非常消耗cpu和記憶體,會把jvm内部給鎖死,在當時的一瞬間會卡死,這也是安卓比蘋果卡的原因,蘋果的底層是實時回收的。

新生代垃圾回收過程(小gc算法):

jvm

老年代垃圾回收:

老年人垃圾回收比新生代要簡單許多,大體可分為兩個過程:

老年代在回收時首先要周遊老年代區域所有的對象,然後标記不再使用的對象。

清理不再使用的的對象。

老年代區域的垃圾回收頻率比新生代要少,但是老年代在垃圾回收時是最卡的時候,因為要周遊整個老年代區域。

新生代、老年代、持久代當中的空間大小是由我們進行指定的,但是并不能胡亂指定,要根據自己目前的業務進行指定。

jvm

我們可以在tomcat的配置檔案裡面指定,向jvm傳遞參數,也可以在指令行的當中用環境變量指定。

-xmx=新生代總空間+老年代總空間

-xx:maxnewsize新生代總空間

-xx:newsize新生代初始空間,不算預留白間,所謂的初始空間就是一開始的時候是多大

-xms是新生代的初始空間和老年代的初始空間

老年代空間無法指定,用總空間減去新生代空間即為老年代空間,也就是說老年代空間是計算出來的。

-xx:maxpermsize持久代的總空間大小

-xx:permsize持久代的初始空間大小

catalina.sh當中有兩個環境變量

catalina_opts:僅對啟動運作tomcat執行個體的java虛拟機有效。

java_opts:對本機上的所有java虛拟機有效。

通過指令行的環境變量也可以向jvm傳遞參數,比如: