java虛擬機(jī)

          JVM specification對(duì)JVM內(nèi)存的描述

          首先我們來(lái)了解JVM specification中的JVM整體架構(gòu)。如下圖:

           


              
          主要包括兩個(gè)子系統(tǒng)和兩個(gè)組件: Class loader(類裝載器) 子系統(tǒng),Execution engine(執(zhí)行引擎) 子系統(tǒng);Runtime data area (運(yùn)行時(shí)數(shù)據(jù)區(qū)域)組件, Native interface(本地接口)組件。
               Class loader
          子系統(tǒng)的作用 :根據(jù)給定的全限定名類名( java.lang.Object)來(lái)裝載class文件的內(nèi)容到 Runtime data area中的method area(方法區(qū)域)Javsa程序員可以extends java.lang.ClassLoader類來(lái)寫(xiě)自己的Class loader
                Execution engine
          子系統(tǒng)的作用 :執(zhí)行classes中的指令。任何JVM specification實(shí)現(xiàn)(JDK)的核心是Execution engine 換句話說(shuō):Sun JDK IBMJDK好壞主要取決于他們各自實(shí)現(xiàn)的Execution  engine的好壞。每個(gè)運(yùn)行中的線程都有一個(gè)Execution engine的實(shí)例。
               Native interface
          組件 :與native libraries交互,是其它編程語(yǔ)言交互的接口。 
               Runtime data area
          組件:這個(gè)組件就是JVM中的內(nèi)存

          • 運(yùn)行時(shí)數(shù)據(jù)組件的詳解介紹:
              

          Runtime data area 主要包括五個(gè)部分:Heap (堆), Method Area(方法區(qū)域), Java Stack(java的棧), Program Counter(程序計(jì)數(shù)器), Native method stack(本地方法棧)。Heap 和Method Area是被所有線程的共享使用的;而Java stack, Program counter 和Native method stack是以線程為粒度的,每個(gè)線程獨(dú)自擁有。

          Heap
          Java程序在運(yùn)行時(shí)創(chuàng)建的所有類實(shí)或數(shù)組都放在同一個(gè)堆中。
          而一個(gè)Java虛擬實(shí)例中只存在一個(gè)堆空間,因此所有線程都將共享這個(gè)堆。每一個(gè)java程序獨(dú)占一個(gè)JVM實(shí)例,因而每個(gè)java程序都有它自己的堆空間,它們不會(huì)彼此干擾。但是同一java程序的多個(gè)線程都共享著同一個(gè)堆空間,就得考慮多線程訪問(wèn)對(duì)象(堆數(shù)據(jù))的同步問(wèn)題。 (這里可能出現(xiàn)的異常java.lang.OutOfMemoryError: Java heap space)

          JVM堆一般又可以分為以下三部分:

          Ø Perm

          Perm代主要保存class,method,filed對(duì)象,這部門的空間一般不會(huì)溢出,除非一次性加載了很多的類,不過(guò)在涉及到熱部署的應(yīng)用服務(wù)器的時(shí)候,有時(shí)候會(huì)遇到java.lang.OutOfMemoryError : PermGen space 的錯(cuò)誤,造成這個(gè)錯(cuò)誤的很大原因就有可能是每次都重新部署,但是重新部署后,類的class沒(méi)有被卸載掉,這樣就造成了大量的class對(duì)象保存在了perm中,這種情況下,一般重新啟動(dòng)應(yīng)用服務(wù)器可以解決問(wèn)題。

          Ø Tenured

          Tenured區(qū)主要保存生命周期長(zhǎng)的對(duì)象,一般是一些老的對(duì)象,當(dāng)一些對(duì)象在Young復(fù)制轉(zhuǎn)移一定的次數(shù)以后,對(duì)象就會(huì)被轉(zhuǎn)移到Tenured區(qū),一般如果系統(tǒng)中用了application級(jí)別的緩存,緩存中的對(duì)象往往會(huì)被轉(zhuǎn)移到這一區(qū)間。

          Ø Young

          Young區(qū)被劃分為三部分,Eden區(qū)和兩個(gè)大小嚴(yán)格相同的Survivor區(qū),其中Survivor區(qū)間中,某一時(shí)刻只有其中一個(gè)是被使用的,另外一個(gè)留做垃圾收集時(shí)復(fù)制對(duì)象用,在Young區(qū)間變滿的時(shí)候,minor GC就會(huì)將存活的對(duì)象移到空閑的Survivor區(qū)間中,根據(jù)JVM的策略,在經(jīng)過(guò)幾次垃圾收集后,任然存活于Survivor的對(duì)象將被移動(dòng)到Tenured區(qū)間。


          Method area
          在Java虛擬機(jī)中,被裝載的class的信息存儲(chǔ)在Method area的內(nèi)存中。
          當(dāng)虛擬機(jī)裝載某個(gè)類型時(shí),它使用類裝載器定位相應(yīng)的class文件,然后讀入這個(gè)class文件內(nèi)容并把它傳輸?shù)教摂M機(jī)中。緊接著虛擬機(jī)提取其中的類型信息,并將這些信息存儲(chǔ)到方法區(qū)。該類型中的類(靜態(tài))變量同樣也存儲(chǔ)在方法區(qū)中。與Heap 一樣,method area是多線程共享的,因此要考慮多線程訪問(wèn)的同步問(wèn)題。比如,假設(shè)同時(shí)兩個(gè)線程都企圖訪問(wèn)一個(gè)名為L(zhǎng)ava的類,而這個(gè)類還沒(méi)有內(nèi)裝載入虛擬機(jī),那么,這時(shí)應(yīng)該只有一個(gè)線程去裝載它,而另一個(gè)線程則只能等待。 (這里可能出現(xiàn)的異常java.lang.OutOfMemoryError: PermGen full)

          Java stack
                 Java stack以幀為單位保存線程的運(yùn)行狀態(tài)。虛擬機(jī)只會(huì)直接對(duì)Java stack執(zhí)行兩種操作:以幀為單位的壓棧或出棧。
          每當(dāng)線程調(diào)用一個(gè)方法的時(shí)候,就對(duì)當(dāng)前狀態(tài)作為一個(gè)幀保存到java stack中(壓棧);當(dāng)一個(gè)方法調(diào)用返回時(shí),從java stack彈出一個(gè)幀(出棧)。棧的大小是有一定的限制,這個(gè)可能出現(xiàn)StackOverFlow問(wèn)題。 下面的程序可以說(shuō)明這個(gè)問(wèn)題。

           

          public class TestStackOverFlow {
           
               public static void main(String[] args) {
           
                      Recursive r = new Recursive();
                      r.doit(10000);
                      // Exception in thread "main" java.lang.StackOverflowError
               }
           
          }
           
          class Recursive {
           
               public int doit(int t) {
                      if (t <= 1) {
                              return 1;
                      }
                      return t + doit(t - 1);
               }
           
          }

           

          Program counter
          每個(gè)運(yùn)行中的Java程序,每一個(gè)線程都有它自己的PC寄存器,也是該線程啟動(dòng)時(shí)創(chuàng)建的。PC寄存器的內(nèi)容總是指向下一條將被執(zhí)行指令的餓&ldquo;地址&rdquo;,這里的&ldquo;地址&rdquo;可以是一個(gè)本地指針,也可以是在方法區(qū)中相對(duì)應(yīng)于該方法起始指令的偏移量。

          Native method stack
          對(duì)于一個(gè)運(yùn)行中的Java程序而言,它還能會(huì)用到一些跟本地方法相關(guān)的數(shù)據(jù)區(qū)。當(dāng)某個(gè)線程調(diào)用一個(gè)本地方法時(shí),它就進(jìn)入了一個(gè)全新的并且不再受虛擬機(jī)限制的世界。本地方法可以通過(guò)本地方法接口來(lái)訪問(wèn)虛擬機(jī)的運(yùn)行時(shí)數(shù)據(jù)區(qū),不止與此,它還可以做任何它想做的事情。比如,可以調(diào)用寄存器,或在操作系統(tǒng)中分配內(nèi)存等。總之,本地方法具有和JVM相同的能力和權(quán)限。 (這里出現(xiàn)JVM無(wú)法控制的內(nèi)存溢出問(wèn)題native heap OutOfMemory )

          JVM提供了相應(yīng)的參數(shù)來(lái)對(duì)內(nèi)存大小進(jìn)行配置。



          正如上面描述,JVM中堆被分為了3個(gè)大的區(qū)間,同時(shí)JVM也提供了一些選項(xiàng)對(duì)Young,Tenured的大小進(jìn)行控制。

          Ø Total Heap 

          -Xms :指定了JVM初始啟動(dòng)以后初始化內(nèi)存

          -Xmx:指定JVM堆得最大內(nèi)存,在JVM啟動(dòng)以后,會(huì)分配-Xmx參數(shù)指定大小的內(nèi)存給JVM,但是不一定全部使用,JVM會(huì)根據(jù)-Xms參數(shù)來(lái)調(diào)節(jié)真正用于JVM的內(nèi)存

          -Xmx -Xms之差就是三個(gè)Virtual空間的大小

          Ø Young Generation

          -XX:NewRatio=8意味著tenured  young的比值81,這樣eden+2*survivor=1/9

          堆內(nèi)存

          -XX:SurvivorRatio=32意味著eden和一個(gè)survivor的比值是321,這樣一個(gè)Survivor就占Young區(qū)的1/34.

          -Xmn 參數(shù)設(shè)置了年輕代的大小

          Ø Perm Generation

          -XX:PermSize=16M -XX:MaxPermSize=64M

          Thread Stack

          -XX:Xss=128K

           


          posted on 2012-02-27 15:35 陳睿 閱讀(525) 評(píng)論(1)  編輯  收藏 所屬分類: 高級(jí)

          評(píng)論

          # 一點(diǎn)不同的看法, 請(qǐng)教下[未登錄](méi) 2012-10-11 15:59 帶著愛(ài)遠(yuǎn)行

          博主好, 文章很好。但我對(duì)于運(yùn)行時(shí)組件的那幅圖native處的調(diào)用有點(diǎn)不明白, 在jvm規(guī)范中并沒(méi)有說(shuō)明會(huì)去調(diào)用操作系統(tǒng)的內(nèi)存, 不知哪里有依據(jù)可以得出這個(gè)結(jié)論。
          原話是:native method stacks are typically allocated per thread when each thread is created.
          另外有點(diǎn)不明白的是,既然是調(diào)用操作系統(tǒng)的內(nèi)存,那么為每個(gè)線程分配native method stacks又有什么意義呢,這塊內(nèi)存用來(lái)保存什么?
          最后請(qǐng)教下運(yùn)行時(shí)組件的那幅圖是不是博主自己畫(huà)的,問(wèn)題比較多,哈哈。  回復(fù)  更多評(píng)論   

          導(dǎo)航

          <2012年10月>
          30123456
          78910111213
          14151617181920
          21222324252627
          28293031123
          45678910

          統(tǒng)計(jì)

          常用鏈接

          留言簿

          隨筆分類

          隨筆檔案

          搜索

          最新評(píng)論

          閱讀排行榜

          評(píng)論排行榜

          主站蜘蛛池模板: 麻江县| 乐业县| 庆阳市| 离岛区| 凤翔县| 同心县| 如皋市| 和硕县| 资兴市| 田东县| 西盟| 南京市| 香格里拉县| 丰都县| 河西区| 突泉县| 育儿| 清原| 忻州市| 兴和县| 新巴尔虎右旗| 乐至县| 吉首市| 乌兰察布市| 黑水县| 慈溪市| 勐海县| 霍山县| 吴忠市| 济南市| 安徽省| 玉龙| 耒阳市| 霍山县| 芦山县| 故城县| 舞阳县| 古蔺县| 镇坪县| 麻阳| 昔阳县|