Java體系和一些基本概念
原文連結:http://www.189works.com/article-42350-1.html
Java平台的結構圖:
JVM與JRE、JDK關係?
JVM:Java Virtual Machine(Java虛擬機器),負責執行符合規範的Class檔案
JRE: Java Runtime Environment (java運行環境),包含JVM和類庫
JDK: Java Development Kit(java開發套件),包含JRE和開發套件,例如javac、javah
JVM所處的位置:
我們通常工作中所接觸的基本是Java庫和應用以及Java核心類庫,知曉如何使用就可以了,但是歸根結底代碼都是要編譯成class檔案由Java虛擬機器
執行的,所產生的結果或者現象都可以通過Java虛擬機器的運行機制來解釋。一些相同的代碼會由於虛擬機器的實現不同而產生不同結果。
Class檔案格式
編譯後被Java虛擬機器所執行的代碼使用了一種平台中立(不依賴於特定硬體及作業系統的)的二進位格式來表示,並且經常(但並非絕對)以檔案的形
式儲存,因此這種格式被稱為Class檔案格式。Class檔案格式中精確地定義了類與介面的表示形式,包括在平台相關的目標檔案格式中一些細節上的慣例,
例如位元組序(Byte Ordering)等。
正如概念所說,Java為了能夠實現平台無關性,制定了一套自己的二進位格式,並經常以檔案的方式儲存,稱為Class檔案。這樣在不同平台上,只要
都安裝了Java虛擬機器,那麼都可以運行相同的Class檔案。
資料類型
與Java程式語言中的資料類型相似,Java虛擬機器可以操作的資料類型可分為兩類:原始類型(Primitive Types,也經常翻譯為原生類型或者基本類
型)和引用類型(Reference Types)。與之對應,也存在有原始值(Primitive Values)和引用值(Reference Values)兩種類型的數值可用於變數
賦值、參數傳遞、方法返回和運算操作。
基本類型和參考型別的具體情況見:
Java虛擬機器希望更多的類型檢查放在編譯期就完成,在運行期不需要進行這些操作。其中基本類型達到了這樣的要求,在運行期間不需要對其進行類型
檢查,也不用和參考型別區分開。這是通過虛擬機器的位元組碼指令完成的,不同類型的位元組碼指令中都包含了相應的資料類型。
整形類型和整型值的取值範圍如下:
對於byte類型,取值範圍是從-128至127(-27至27-1),包括-128和127。
對於short類型,取值範圍是從−32768至32767(-215至215-1),包括−32768和32767。
對於int類型,取值範圍是從−2147483648至2147483647(-231至231-1),包括−2147483648和2147483647。
對於long類型,取值範圍是從−9223372036854775808至9223372036854775807(-263至263-1),包括−9223372036854775808和
9223372036854775807。
對於char類型,取值範圍是從0至65535,包括0和65535。
浮點類型、取值集合和浮點值:
浮點類型包含32位單精確度的float類型和64位雙精確度的double類型兩種,浮點數除了包括正負帶符號可數的數值,還包括了正負零、正負無窮大和一
個特殊的“非數字”標識(Not-a-Number,下文用NaN表示)。NaN值用於表示某些無效的運算操作,例如除數為零等情況。所有Java虛擬機器的實現都必
須支援兩種標準的浮點數值集合:單精確度浮點數集合和雙精確度浮點數集合。
returnAddress類型和值:
returnAddress類型會被Java虛擬機器的jsr、ret和jsr_w指令所使用。returnAddress類型的值指向一條虛擬機器指令的作業碼。與前面介紹的那些數
值類的原始類型不同,returnAddress類型在Java語言之中並不存在相應的類型,也無法在程式運行期間更改returnAddress類型的值。
boolean類型:
Java虛擬機器不提供操作boolean類型的位元組碼指令,程式在編譯後boolean類型都轉化成了int操作。但是Java虛擬機器支援boolean類型的數組的訪
問和修改,共用byte類型數組的位元組碼指令。
運行時資料區
Java虛擬機器定義了若干種程式運行期間會使用到的運行時資料區,其中有一些會隨著虛擬機器啟動而建立,隨著虛擬機器退出而銷毀。另外一些則是與線程
一一對應的,這些與線程對應的資料區域會隨著線程開始和結束而建立和銷毀。
Java虛擬機器的邏輯構成:
可以看出Java虛擬機器的運行時資料區包括了:方法區、Java堆、Java虛擬機器棧、PC寄存器、本地方法棧。
PC寄存器:
每個Java虛擬機器線程都有自己的PC寄存器。在某個線程被建立時,會獲得一個PC寄存器。線程當前執行的方法稱為當前方法,PC寄存器用來存
放當前方法中當前執行的位元組碼指令的地址,如果當前方法是本地方法(Native),那麼寄存器存放undefined。寄存器的大小至少應該能夠存放一個
returnAddress類型的資料或者與平台相關的本地指標的值。
Java虛擬機器棧:
每個Java虛擬機器線程都有自己的Java虛擬機器棧。Java虛擬機器棧用來存放棧幀,而棧幀主要包括了:局部變數表、運算元棧、動態連結。
Java虛擬機器使用局部變數表來完成方法調用時的參數傳遞。局部變數表的長度在編譯期已經決定了並儲存於類和介面的二進位表示中,一個局部變數可
以儲存一個類型為boolean、byte、char、short、float、reference 和 returnAddress的資料,兩個局部變數可以儲存一個類型為long和double的
數據。
Java虛擬機器提供一些位元組碼指令來從局部變數表或者對象執行個體的欄位中複製常量或變數值到運算元棧中,也提供了一些指令用於從運算元棧取走資料、
操作資料和把操作結果重新入棧。在方法調用的時候,運算元棧也用來準備調用方法的參數以及接收方法返回結果。
每個棧幀中都包含一個指向運行時常量區的引用支援當前方法的動態連結。在Class檔案中,方法調用和訪問成員變數都是通過符號引用來表示的,動
態鏈接的作用就是將符號引用轉化為實際方法的直接引用或者訪問變數的運行是記憶體位置的正確位移量。
總的來說,Java虛擬機器棧是用來存放局部變數和過程結果的地方。
Java虛擬機器棧可能發生如下異常情況:
如果線程請求分配的棧容量超過Java虛擬機器棧允許的最大容量時,Java虛擬機器將會拋出一個StackOverflowError異常。
如果Java虛擬機器棧可以動態擴充,並且擴充的動作已經嘗試過,但是目前無法申請到足夠的記憶體去完成擴充,或者在建立新的線程時沒有足夠的記憶體去
建立對應的虛擬機器棧,那Java虛擬機器將會拋出一個OutOfMemoryError異常。
Java堆:
Java堆在虛擬機器啟動的時候被建立,Java堆主要用來為類執行個體對象和數組分配記憶體。Java虛擬機器規範並沒有規定對象在堆中的形式。
Java堆可能發生如下異常情況:
如果實際所需的堆超過了自動記憶體管理系統能提供的最大容量,那Java虛擬機器將會拋出一個OutOfMemoryError異常。
方法區:
方法區在虛擬機器啟動的時候被建立,它儲存了每一個類的結構資訊,例如運行時常量池、欄位和方法資料、建構函式和普通方法的位元組碼內容、還包括
一些在類、執行個體、介面初始化時用到的特殊方法。
方法區可能發生如下異常情況:
如果方法區的記憶體空間不能滿足記憶體配置請求,那Java虛擬機器將拋出一個OutOfMemoryError異常.
運行時常量池:
運行時常量池(Runtime Constant Pool)是每一個類或介面的常量池的運行時表示形式,它包括了若干種不同的常量:從編譯期可知的數值字面量
到必須運行期解析後才能獲得的方法或欄位引用。運行時常量池在方法區中。
在建立類和介面的運行時常量池時,可能會發生如下異常情況:
當建立類或介面的時候,如果構造運行時常量池所需要的記憶體空間超過了方法區所能提供的最大值,那Java虛擬機器將會拋出一個OutOfMemoryError
異常。
本地方法棧:
本地方法棧用於支援native方法的運行。