天天看點

JVM基礎知識(原創)

jvm簡介

jdk記憶體

JVM基礎知識(原創)

java 的記憶體模型分為

young(年輕代也叫new區)

young分為 eden 區和兩個survivor 區(from和to,這兩個survivor區大小嚴格一至),新的對象執行個體總是首先放在eden 區,survivor區作為eden區和tenure(終生代)的緩沖,可以向 tenure(終生代)轉移活動的對象執行個體。

tenured(終身代,也叫old區)

tenure中存放生命周期長久的執行個體對象,但并不是如它的名字那樣是終生的,裡面的對象照樣會被回收掉。

young和tenure共同組成了堆記憶體,也就是heap記憶體或heap區。

perm(永久代)

有些舊版本也叫作:new old perm 叫法不同,表達的意思卻是基本相同。perm則是非堆記憶體的組成部分。主要存放加載的class類級對象如class本身,method,field等等。

virtual區

在jvm啟動時,就已經保留了固定的記憶體空間給heap記憶體,這部分記憶體并不一定都會被jvm使用,但是可以确定的是這部分保留的記憶體不會被其他程序使用。這部分記憶體大小由 -xmx 參數指定。

而另一部分記憶體在jvm啟動時就配置設定給jvm,作為jvm的初始heap記憶體使用。影響這個的參數是 -xms ,如果 -xms 指定的值比-xmx 的小,那麼兩者的內插補點就是virtual記憶體值。随着程式的運作,eden區,tenured區和perm區會逐漸使用保留的virtual空間。

如果沒有具體指定,初始和最大堆記憶體将根據機器的記憶體計算得出。參數defaultinitialramfraction 和 defaultmaxramfraction 會影響最終的結果,如下表所示:

formuladefault

initial heap size memory / defaultinitialramfraction memory / 64

maximum heap size min(memory / defaultmaxramfraction, 1gb) min(memory / 4, 1gb)

可以看到堆記憶體預設值最大不會超過1g。

jvm會根據堆記憶體的使用情況自動決定何時擴張和縮減實際堆記憶體的大小,可以用vm參數 -xx:minheapfreeratio= 和 -xx:maxheapfreeratio= 使用堆記憶體空閑百分比來定義,一般在32位機器上的預設值如下:

parameterdefault value

minheapfreeratio 40

maxheapfreeratio 70

-xms 3670k

-xmx 64m

-xms/-xmx:

java heap并不是越大越好,對他的一般優化原則是夠用的情況下,盡可能的小,因為太大的話會浪費記憶體,同時影響gc的效率。當空閑堆記憶體所占堆記憶體百分比低于40%,jvm就會試圖擴張堆記憶體空間;當空閑堆記憶體所占堆記憶體百分比高于70%,jvm就會試圖壓縮堆記憶體空間。

ps:以上預設值在不同平台會有不同的值,如果是64位系統,這些值一般需要擴張30%,來容納在64位系統下變大的對象。

gc

gc是garbage collection的縮寫,即垃圾回收機制,在java中開發人員無需使用指針來管理記憶體,gc是jvm對記憶體(實際上就是對象)進行管理的方式。

第一種為單線程gc,也是預設的gc。,該gc适用于單cpu機器。

第二種為throughput gc,是多線程的gc,适用于多cpu,使用大量線程的程式。第二種gc與第一種gc相似,不同在于gc在收集young區是多線程的,但在old區和第一種一樣,仍然采用單線程。-xx:+useparallelgc參數啟動該gc。

第三種為concurrent low pause gc,類似于第一種,适用于多cpu,并要求縮短因gc造成程式停滞的時間。這種gc可以在old區的回收同時,運作應用程式。-xx:+useconcmarksweepgc參數啟動該gc。

第四種為incremental low pause gc,适用于要求縮短因gc造成程式停滞的時間。這種gc可以在young區回收的同時,回收一部分old區對象。-xincgc參數啟動該gc。

相關調整的目标:

短生命周期的對象不要進入old區

短生命周期的對象在minor gc的時候幹掉

長生命周期的對象要放到old區

長生命周期的對象可以被full gc清理掉,但是full gc要調整到盡量少發生

jvm中的classloader

類加載器(class loader)用來加載java類到java虛拟機中。一般來說,java虛拟機使用java類的方式如下:java源程式(.java檔案)在經過java編譯器編譯之後就被轉換成java位元組代碼(.class檔案)。類加載器負責讀取java位元組代碼,并轉換成java.lang.class類的一個執行個體。每個這樣的執行個體用來表示一個java類。

java程式是由許多獨立的類檔案組成的,每個檔案對應于一個java類。此外,這些檔案并非立即全部加載如記憶體,而是根據程式需要裝入記憶體。classloader便是jvm中将類裝入記憶體的零件,使用者可以定制自己的classloader。jvm中預設的classloader可以完成将本地已檔案系統裝入類檔案的任務。使用者指定的classloader可以擁有jvm預設的classloader所不具有的功能。例如:使用者可以使用自己建立的classloader從非本地硬碟或者從網絡裝入可執行内容。

java應用環境中不同的class分别由不同的classloader負責加載。

一個jvm中預設的classloader有bootstrap classloader、extension classloader、app classloader,分别各司其職:

bootstrap classloader:用來在jvm啟動時加載核心類庫,主要是 %jre_home/lib/ 目錄下的rt.jar、resources.jar、charsets.jar和class等

extension classloader:負責加載java擴充類,主要是%jre_home/lib/ext目錄下的jar和class

app classloader:負責加載目前java應用classpath變量中的所有類。

其中bootstrap classloader是jvm級别的,由c++編寫;extension classloader、app classloader都是java類,都繼承自urlclassloader超類。

bootstrap classloader由jvm啟動,然後初始化sun.misc.launcher ,sun.misc.launcher初始化extension classloader、app classloader。

下圖是classloader的加載類流程圖,以加載一個類的過程類示例說明整個classloader的過程。

JVM基礎知識(原創)

java 類加載器層次結構 

類加載器包含具有父類加載器和子類加載器的層次結構。父類加載器和子類加載器之間的關系類似于超類和子類之間的對象關系。引導類加載器是 java 類加載器層次結構的根。java 虛拟機 (jvm) 建立引導類加載器,它将加載 jvm 中包含的 java development kit (jdk) 内部類和 java.* 包。(例如,引導類加載器加載 java.lang.string。)

擴充類加載器是引導類加載器的子類加載器。擴充類加載器加載 jdk 的擴充目錄中包含的所有 jar 檔案。這是一種無需在類路徑中添加條目即可擴充 jdk 的便捷方法。但擴充目錄中的所有内容都必須是自包含的,且隻能引用擴充目錄中的類或 jdk 類。

系統類路徑類加載器擴充 jdk擴充類加載器。系統類路徑類加載器加載 jvm 類路徑中的類。

加載類 

類加載器在加載類時使用委托模型。類加載器實作首先檢查其緩存,檢視是否已經加載所請求的類。由于不重複從磁盤中加載類,而是使用該類在緩存記憶體中的副本,是以,這種類驗證可以提高性能。如果在類緩存中找不到該類,則目前類加載器會要求其父類加載器提供該類。僅當父類加載器也無法加載該類時,該類加載器才會嘗試加載該類。如果某個類既存在于父類加載器中,又存在于子類加載器中,則将加載父類加載器中的類。遵循這種委托模型可以避免同時加載多份相同的類。加載多份相同的類會引發 classcastexception。

類加載器會先要求其父加載器加載類,然後再嘗試自己加載該類。

參考至:《叱咤風雲:weblogic企業級運維實戰》戴冠平著

             http://longdick.iteye.com/blog/442213

             http://songyishan.iteye.com/blog/1135183

             http://hi.baidu.com/love200456/blog/item/9d4d70fbdc38c970024f564f.html

             http://blog.sina.com.cn/s/blog_677e5328010109a3.html

本文原創,轉載請注明出處、作者

如有錯誤,歡迎指正

郵箱:[email protected]

作者:czmmiao  文章出處:http://czmmiao.iteye.com/blog/1614446