2004-09-27
第三章:jvm結構
3.1數(shù)據(jù)類型
基本類型和引用類型
基本值和引用值
數(shù)據(jù)不需要做標記或者可被檢查以確定類型。也就導致jvm的指令集是針對特定類型的值的。
jvm包含對對象的顯式支持(引用類型)
3.2基本類型和值
基本類型--returnAddress類型(jvm指令的操作碼的指針,不是java類型)
?--數(shù)值類型--整型--byte
???--short
???--int
???--long
??? --浮點型--float
???? --double
???--char
jvm中沒有boolean類型,java中的boolean類型的操作被翻譯為int類型進行操作。
問題:在數(shù)值類型中提及的NaN值對應于java里的什么情況
3.3引用類型和值
有三種引用類型:類類型,接口類型,數(shù)組類型
3.4字
jvm中沒有指定數(shù)據(jù)類型的存儲器大小,只是指定了一個“字”的概念,一個字足以持有byte,int,char,short,float,returnAddress,refrence的值,兩個字足夠大持有double,long的值。
一般來說,一個字的大小是主機平臺的一個指針的大小,32位機上,字是32位,64位機上,字是64位的,但這是實現(xiàn)決定的,而不是jvm規(guī)范決定的。
3.5運行期數(shù)據(jù)
pc(程序計數(shù)器)寄存器:
每個jvm線程有自己的pc寄存器,在任何點,每個jvm線程執(zhí)行一個單個方法的 代碼,這個方法被稱為那個線程的當前方法。如果方法是native,則pc寄存器的值沒有定義,如果不是,則pc寄存器中存放當前正在執(zhí)行的jvm指令的地址。
pc寄存器占一個字寬。
棧:
每個jvm線程都有私有的棧。等價于傳統(tǒng)語言的棧,它持有局部變量和部分結果。并參與部分方法的調用和返回。(由于java框架是可以堆分配的,所以java的棧的存儲空間可以是不連續(xù)的)
java棧可以是固定大小或者是動態(tài)的。jvm實現(xiàn)可以向程序員提供對java棧的初始大小以及動態(tài)情況下的最大和最小值的控制。
如果固定大小而且線程需要的棧大于棧的大小,則出現(xiàn)stackoverflowError
如果動態(tài)大小但存儲器沒有足夠空間,則出現(xiàn)outOfMemoryError
Sun的jdk1.0.2版jvm實現(xiàn)中,java棧是不連續(xù)、動態(tài)的,不收縮,在線程消亡時被回收。java棧的大小的限制可以在jvm啟動時用“-oss”標志設置。
堆:
java有一個所有線程共享的堆。堆是用于分配所有類實例和數(shù)組的運行期數(shù)據(jù)區(qū)。
堆在jvm啟動時創(chuàng)建,由garbage collector回收。
堆可以是固定的,也可以動態(tài)擴展,并且支持自動收縮,存儲器無需連續(xù)。
jvm實現(xiàn)可以向程序員提供堆初始大小以及動態(tài)情況下的最大和最小值的控制。
如果要求的堆比系統(tǒng)能夠擁有的堆大,則出現(xiàn)OutOfMemoryError
Sun的jdk1.0.2中,堆是動態(tài)的,從不收縮它的堆,它的初始值和最大值在啟動時用“-ms”和“-mx”指定。
方法區(qū):
方法區(qū)類似于傳統(tǒng)語言中編譯后代碼的存儲區(qū),存儲每個類結構例如:常數(shù)池、域、方法數(shù)據(jù)。
方法區(qū)是虛擬機建立的時候啟動的,邏輯上是垃圾回收實現(xiàn)的一部分,但可以不實現(xiàn)。
方法區(qū)可以固定大小,可以動態(tài),可以收縮,無需連續(xù)存儲器。
jvm實現(xiàn)可以向程序員提供方法區(qū)初始大小以及動態(tài)情況下的最大和最小值的控制。
outofmemory異常
sun的jdk1.0.2中,仿佛去是動態(tài)的,不收縮的,不提供程序員對其最大最小值的控制。
常數(shù)池:
常數(shù)池是每個類或接口的constant_pool的運行期表示。功能類似于傳統(tǒng)語言的符號表,但含更寬的數(shù)據(jù)范圍。(詳細見第五章)
自身方法棧(估計應該是native method stack)
其管理和普通棧類似,每個線程一個,線程創(chuàng)建時創(chuàng)建,只是使用非java的native語言(如C)寫成,以支持native方法。
Sun的jdk1.0.2版jvm實現(xiàn)中,java棧是固定大小。java棧的大小的限制可以在jvm啟動時用“-oss”標志設置。
3.6框架
jvm frame用于存儲數(shù)據(jù)和部分結果,以及動態(tài)鏈接,返回方法的值,和調度異常。
每次java方法調用時創(chuàng)建一個新的框架,當方法結束的時候,框架撤銷。框架從創(chuàng)建它的線程的棧里分配,每個框架有自己的局部變量集和操作數(shù)棧(這些可以一次分配,因為都是編譯期可知的)。
對于一個給定線程的任何點,只有一個活躍框架,稱為當前框架,局部變量和操作數(shù)棧上的操作總是引用當前框架。
局部變量:
每個jvm frame包含一組局部變量,局部變量總是一個字寬,long型,double型存為兩個局部變量。
操作數(shù)棧:
每個jvm frame包含一個操作數(shù)棧,絕大多數(shù)java操作從當前操作數(shù)棧取值。
動態(tài)連接:
jvm frame通過包含一個對當前類的常數(shù)池的引用來達到動態(tài)鏈接的目的,java 的class文件仍然可以使用符號引用訪問變量或方法。
java中的i=i++從這一章來理解應該是和框架(jvm frame)這個概念有關,也就是++操作符被實現(xiàn)成為了一個方法,而不是一個虛擬機指令,這樣就可以解釋了,但是目前還沒有看到有++操作符應該被實現(xiàn)為一個方法的說明,另外java的方法調用是值傳參的,這種情況應該也不會出現(xiàn)值回寫的情況.
看至3。6結束。
3.7對象的表示
jvm不對對象表示要求任何特殊的內(nèi)部結構。
在sun公司的jdk實現(xiàn)中,對象實例就是指向一個句柄的指針,而這個句柄本身又包括兩個指針:1、一個指向包含該對象方法而代表該對象類型的class對象的指針,2、另一個指向在java堆中為該對象實例分配的存儲區(qū)域。
別的jvm實現(xiàn)可以采用諸如:直接插入高速緩存技術,等。
3.8特殊的初始化方法
實例初始化:構造函數(shù)作為具有特殊名字《init》的實例初始化方法出現(xiàn),方法的名字由編譯器提供,這個方法由jvm在內(nèi)部由invokespecial指令調用,只能使用于未初始化的實例上,不能被java程序員使用。
類和接口的初始化:類和接口的初始化具有特殊的名字《cinit》,方法的名稱由編譯器提供,該方法由jvm顯示調用,從不直接被java代碼和jvm指令調用,只是作為類初始化進程的一部分被間接的調用。
3.9異常
異常一層層向上拋,丟棄當前層的操作數(shù)棧和局部變量,知道遇到catch為止,如果到頂層還沒有catch,當前線程將被結束。
3.10class文件格式
class文件是平臺無關格式的二進制文件,class文件格式精確定義了文件的內(nèi)容。
3.11指令集概述
一個jvm指令由一個字節(jié)的操作碼后跟0個或多個操作數(shù)構成。操作數(shù)的數(shù)目由操作碼決定。
當操作數(shù)多于一個字節(jié)的時候,以高位字節(jié)在前的方式存儲。
字節(jié)碼指令流只是單字節(jié)對齊的(除了tableswitch,和lookupswitch的特殊指令對操作數(shù)的特殊要求),放棄了數(shù)據(jù)對齊,反映了對數(shù)據(jù)緊湊性的偏好,而排除了可能提高jvm仿真器性能的某些實現(xiàn)技術。
jvm指令中絕大多數(shù)是類型相關的,也就是作用于特定類型的操作數(shù)的。并在該指令的助記符中顯示的標識出來。
具體的指令集后面細說。
3.12公共設計、私有實現(xiàn)
公共概念:class文件格式和jvm指令集