<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    java虛擬機(jī)

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

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

     


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

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

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

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

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

    Ø Perm

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

    Ø Tenured

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

    Ø Young

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


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

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

     

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

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

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



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

    Ø Total Heap 

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

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

    -Xmx -Xms之差就是三個Virtual空間的大小

    Ø Young Generation

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

    堆內(nèi)存

    -XX:SurvivorRatio=32意味著eden和一個survivor的比值是321,這樣一個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 陳睿 閱讀(523) 評論(1)  編輯  收藏 所屬分類: 高級

    評論

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

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

    導(dǎo)航

    <2012年2月>
    2930311234
    567891011
    12131415161718
    19202122232425
    26272829123
    45678910

    統(tǒng)計

    常用鏈接

    留言簿

    隨筆分類

    隨筆檔案

    搜索

    最新評論

    閱讀排行榜

    評論排行榜

    主站蜘蛛池模板: 777爽死你无码免费看一二区| 无码天堂亚洲国产AV| 久久精品夜色国产亚洲av| 亚洲精品高清国产一线久久| 中文字幕亚洲天堂| 自拍偷自拍亚洲精品第1页| 久久久久久久亚洲精品| 亚洲综合AV在线在线播放| 三上悠亚亚洲一区高清| 最新亚洲成av人免费看| 伊人久久综在合线亚洲91| 国产亚洲精久久久久久无码| 久久久久久久尹人综合网亚洲| 亚洲国产精品无码专区在线观看| 亚洲国产精品嫩草影院在线观看| 亚洲男人的天堂www| 亚洲AV无码不卡无码| 亚洲熟妇色自偷自拍另类| 亚洲乱码一区二区三区国产精品| 亚洲日韩AV无码一区二区三区人| 亚洲国产成人无码AV在线影院| 美女视频黄频a免费观看| 国产精品免费看久久久香蕉| 日本高清不卡aⅴ免费网站| 一级毛片在线免费观看| 国产92成人精品视频免费| 成人黄动漫画免费网站视频| 国产嫩草影院精品免费网址| 国产成人亚洲影院在线观看| 亚洲av丰满熟妇在线播放| 亚洲一卡2卡3卡4卡国产网站| 亚洲日本成本人观看| 永久免费观看黄网站| 免费国产叼嘿视频大全网站| 91精品免费国产高清在线| 免费激情视频网站| 黑人大战亚洲人精品一区| 亚洲一区精品中文字幕| 亚洲大码熟女在线观看| 日批视频网址免费观看| 中文字幕无码免费久久99|