Java虛擬機(jī)體系結(jié)構(gòu)

          Java虛擬機(jī)體系結(jié)構(gòu)


          方法區(qū)
                   在Java虛擬機(jī)中,被裝載類型的信息存儲(chǔ)在一個(gè)邏輯上被稱為方法區(qū)的內(nèi)存中。
           當(dāng)虛擬機(jī)裝載某個(gè)類型時(shí),它使用類裝載器定位相應(yīng)的class文件,-->讀入這個(gè)class文件(一個(gè)線性的二進(jìn)制流)->將它傳入虛擬機(jī)-->
           虛擬機(jī)提取類型信息,并將信息存入方法區(qū),類型中的類(靜態(tài))變量也存儲(chǔ)在方法區(qū).
           方法區(qū)特點(diǎn):
           1)所有線程共享方法區(qū)。它是線程安全的。
           2)方法區(qū)大小不是固定的。虛擬機(jī)根據(jù)需要自行調(diào)整。
           3)方法區(qū)可以被垃圾回收。
           對于每個(gè)被裝載的類型,虛擬機(jī)會(huì)在方法區(qū)中存儲(chǔ)以下信息。
           
           1)類型的基本信息;
               a)類型的全限定名
               b)類型的直接超類全限定名(除非這個(gè)類型是java.lang.Objet,它沒超類)。
               c)類型是類類型還是接口類型(就是說是一個(gè)類還是一個(gè)接口)。
               d)類型的訪問修飾符(public ,abstract或final的某個(gè)子類)
               e)任何直接超接口的全限定名的有序列表。
               
           2)該類型的常量池
             虛擬機(jī)必須為每個(gè)被裝載的類型維護(hù)一個(gè)常量池。常量池就是該類型所用常量的一個(gè)有序集合,
             包括直接常量(string,integer,floating point常量)和對其他類型、字段和方法的符號(hào)引用。
             池中的數(shù)據(jù)項(xiàng)就像數(shù)組一樣是通過索引訪問的。因?yàn)槌A砍卮鎯?chǔ)了相應(yīng)類型所用到的所有類型、
             字段和方法的符號(hào)引用,所以它在Java程序的動(dòng)態(tài)連接中起著核心的作用。
             
           3)字段信息
             類型中聲明的每一個(gè)字段,方法區(qū)中必須保存下面的信息,字段在類或接口中聲明的順序也必須保存。
             字段名,字段類型,字段修飾符(public private protected static final 等)
             
           4)方法信息
             類型中聲明的每一個(gè)方法,方法區(qū)中必須保存下面的信息,方法在類或接口中聲明的順序也必須保存。
             方法名,返回值類型,參數(shù)數(shù)量和類型(按聲明順序),方法修飾符(public private protected static final 等)
             如果方法不是抽象的或本地的還必須保存:方法字節(jié)碼,操作數(shù)棧和該方法在棧針中局部變量的大小,異常表。
             
           5)除了常量以外的所有類(靜態(tài))變量
             這里主要說下編譯時(shí)常量:就是那些用final聲明以及編譯時(shí)已知的值初始化的類變量(例如:static final int val =5)
             每個(gè)編譯時(shí)常量的類型都會(huì)復(fù)制它所有常量到它自己的常量池中或者它的字節(jié)碼流中(通常情況下編譯時(shí)直接替換字節(jié)碼)。

             
           6)一個(gè)到類classLoader的引用
             指向ClassLoader類的引用  每個(gè)類型被裝載的時(shí)候,虛擬機(jī)必須跟蹤它是由啟動(dòng)類裝載器
             還是由用戶自定義類裝載器裝載的。如果是用戶自定義類裝載器裝載的,那么虛擬機(jī)必須在類
             型信息中存儲(chǔ)對該裝載器的引用:這是作為方法表中的類型數(shù)據(jù)的一部分保存的。
             虛擬機(jī)會(huì)在動(dòng)態(tài)連按期間使用這個(gè)信息。當(dāng)某個(gè)類型引用另一個(gè)類型的時(shí)候,虛擬機(jī)會(huì)請求裝載
             發(fā)起引用類型的類裝載器來裝載被引用的類型。這個(gè)動(dòng)態(tài)連接的過程,對于虛擬機(jī)分離命名空間
             的方式也是至關(guān)重要的。為了能夠正確地執(zhí)行動(dòng)態(tài)連接以及維護(hù)多個(gè)命名空間,虛擬機(jī)需要在方
             法表中得知每個(gè)類都是由哪個(gè)類裝載器裝載的。
             
           7)一個(gè)到Class類的引用
              指向Class類的引用  對于每一個(gè)被裝載的類型(不管是類還是接口),虛擬機(jī)都會(huì)相應(yīng)地為
              它創(chuàng)建一個(gè)java.lang.Class類的實(shí)例(Class實(shí)例放在內(nèi)存中的堆區(qū)),
          而且虛擬機(jī)還必須以某種方式把這個(gè)實(shí)例的引用存儲(chǔ)在方法區(qū)
              
                 為了盡可能提高訪問效率,設(shè)計(jì)者必須仔細(xì)設(shè)計(jì)存儲(chǔ)在方法區(qū)中的類型信息的數(shù)據(jù)結(jié)構(gòu),因此,
          除了以上時(shí)論的原始類型信息,實(shí)現(xiàn)中還可能包括其他數(shù)據(jù)結(jié)構(gòu)以加快訪問原始數(shù)據(jù)的速度,比如方法表。
          虛擬機(jī)對每個(gè)裝載的非抽象類,都生成一個(gè)方法表,把它作為類信息的一部分保存在方法區(qū)。方法表是一個(gè)數(shù)組,
          它的元素是所有它的實(shí)例可能被調(diào)用的實(shí)例方法的直接引用,包括那些從超類繼承過來的實(shí)例方法:(對于抽象類和接口,方法表沒有什么幫
          助,因?yàn)槌绦驔Q不會(huì)生成它們的實(shí)例。)運(yùn)行時(shí)可以通過方法表快速搜尋在對象中調(diào)用的實(shí)例方法。
           
          方法區(qū)使用的例子

           class Lava{
            private int speed = 5;
           
            void flow(){
            
            }
           
           }

           public class Volcano {
            
            public static void main(String args[]){
             
             Lava lava = new Lava();
             
             lava.flow();
            }
           }

            1)虛擬機(jī)在方法區(qū)查找Volcano這個(gè)名字,未果,載入volcano.class文件,并提取相應(yīng)信息
             存入方法區(qū)。
            2)虛擬機(jī)開始執(zhí)行Volcano類中main()方法的字節(jié)碼的時(shí)候,盡管Lava類還沒被裝載,
            但是和大多數(shù)(也許所有)虛擬機(jī)實(shí)現(xiàn)一樣,它不會(huì)等到把程序中用到的所有類都裝載后才開
            始運(yùn)行程序。恰好相反,它只在需要時(shí)才裝載相應(yīng)的類。
            3)main()的第一條指令告知虛擬機(jī)為列在常量池第一項(xiàng)的類分配足夠的內(nèi)存。所以虛擬機(jī)
            使用指向Volcano常量池的指針找到第一項(xiàng),發(fā)現(xiàn)它是一個(gè)對Lava類的符號(hào)引用,然后它就檢查
            方法區(qū),看Lava類是否已經(jīng)被裝載了。
            4)當(dāng)虛擬機(jī)發(fā)現(xiàn)還沒有裝載過名為"Lava"的類時(shí),它就開始查找并裝載文件“Lava.class”,
            并把從讀入的二進(jìn)制數(shù)據(jù)中提取的類型信息放在方法區(qū)中。
            5)虛擬機(jī)以一個(gè)直接指向方法區(qū)Lava類數(shù)據(jù)的指針來替換常量池第—項(xiàng)(就是那個(gè)
            字符串“Lava”)——以后就可以用這個(gè)指針來快速地訪問Lava類了。這個(gè)替換過程稱為常量池
            解析,即把常量池中的符號(hào)引用替換為直接引用:這是通過在方法區(qū)中搜索被引用的元素實(shí)現(xiàn)
            的,在這期間可能又需要裝載其他類。在這里,我們替換掉符號(hào)引用的“直接引用”是一個(gè)本
            地指針。
            6)虛擬機(jī)準(zhǔn)備為一個(gè)新的Lava對象分配內(nèi)存。此時(shí),它又需要方法區(qū)中的信息。還記
            得剛剛放到Volcano類常量池第——項(xiàng)的指針嗎?現(xiàn)在虛擬機(jī)用它來訪問Lava類型信息(此前剛放
            到方法區(qū)中的),找出其中記錄的這樣一個(gè)信息:一個(gè)Lava對象需要分配多少堆空間。
            7)虛擬機(jī)確定一個(gè)Lava對象大小后,就在堆上分配空間,并把這個(gè)對象實(shí)例變量speed初始化為默認(rèn)初始值0
            8)當(dāng)把新生成的Lava對象的引用壓到棧中,main()方法的第一條指令也完成了,指令通過這個(gè)引用
            調(diào)用Java代碼(該代碼把speed變量初始化為正確初始值5).另外用這個(gè)引用調(diào)用Lava對象引用的flow()方法。


                  每個(gè)java虛擬機(jī)實(shí)例都有一個(gè)方法區(qū)以及一個(gè)堆,一個(gè)java程序獨(dú)占一個(gè)java虛擬機(jī)實(shí)例,而每個(gè)java程序都有自己的堆空間,它們不會(huì)彼此干擾,但同一個(gè)java程序的多個(gè)線程共享一個(gè)堆空間。這種情況下要考慮多線程訪問同步問題。
           
          Java棧
                  一個(gè)新線程被創(chuàng)建時(shí),都會(huì)得到自己的PC寄存器和一個(gè)java棧,虛擬機(jī)為每個(gè)線程開辟內(nèi)存區(qū)。這些內(nèi)存區(qū)是私有的,任何線程不能訪問其他線程的PC寄存器和java棧。java棧總是存儲(chǔ)該線程中java方法的調(diào)用狀態(tài)。包括它的局部變量,被調(diào)用時(shí)傳進(jìn)來的參數(shù),它的返回值,以及運(yùn)算的中間結(jié)果等。java棧是由許多棧幀或者說幀組成,一個(gè)棧幀包含一個(gè)java方法的調(diào)用狀態(tài),當(dāng)線程調(diào)用java方法時(shí),虛擬機(jī)壓入一個(gè)新的棧幀到該線程的java棧中。當(dāng)方法返回時(shí),這個(gè)棧幀被從java棧中彈出并拋棄。
          .本地方法棧
                   任何本地方法接口都會(huì)使用某種本地方法餞。當(dāng)線程調(diào)用Java方法時(shí),虛擬機(jī)會(huì)創(chuàng)建一個(gè)新的棧幀井壓人Java棧。
          然而當(dāng)它調(diào)用的是本地方法時(shí),虛擬機(jī)會(huì)保持Java棧不變,不再在線程的Java棧中壓人新的幀,虛擬機(jī)只是簡單地動(dòng)態(tài)連接
          并直接調(diào)用指定的本地方法。可以把這看做是虛擬機(jī)利用本地方法來動(dòng)態(tài)擴(kuò)展自己。

          posted on 2010-07-06 13:47 AK47 閱讀(382) 評(píng)論(0)  編輯  收藏 所屬分類: java相關(guān)

          <2010年7月>
          27282930123
          45678910
          11121314151617
          18192021222324
          25262728293031
          1234567

          導(dǎo)航

          統(tǒng)計(jì)

          常用鏈接

          留言簿

          隨筆分類

          隨筆檔案

          搜索

          最新評(píng)論

          閱讀排行榜

          評(píng)論排行榜

          主站蜘蛛池模板: 枞阳县| 黔东| 赤壁市| 边坝县| 察哈| 海丰县| 辽阳市| 工布江达县| 雷州市| 中卫市| 南开区| 周口市| 孟州市| 桑植县| 雷州市| 麻栗坡县| 嘉黎县| 合山市| 蒙山县| 宜黄县| 洪洞县| 高雄市| 上林县| 常熟市| 固原市| 华蓥市| 麦盖提县| 大邑县| 扎兰屯市| 宜宾县| 巨鹿县| 郸城县| 若羌县| 永福县| 大化| 汽车| 镇赉县| 东明县| 古浪县| 光泽县| 含山县|