JAVA虛擬機體系結構(一)

JAVA虛擬機的生命周期

一個運行時的Java虛擬機實例的天職是:負責運行一個java程序。當啟動一個Java程序時,一個虛擬機實例也就誕生了。當該程序關閉退出,這個虛擬機實例也就隨之消亡。如果同一臺計算機上同時運行三個Java程序,將得到三個Java虛擬機實例。每個Java程序都運行于它自己的Java虛擬機實例中。
  Java虛擬機實例通過調用某個初始類的main()方法來運行一個Java程序。而這個main()方法必須是共有的(public)、靜態的(static)、返回值為void,并且接受一個字符串數組作為參數。任何擁有這樣一個main()方法的類都可以作為Java程序運行的起點。

public class Test {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        System.out.println("Hello World");
    }

}

在上面的例子中,Java程序初始類中的main()方法,將作為該程序初始線程的起點,任何其他的線程都是由這個初始線程啟動的。
  在Java虛擬機內部有兩種線程:守護線程和非守護線程。守護線程通常是由虛擬機自己使用的,比如執行垃圾收集任務的線程。但是,Java程序也可以把它創建的任何線程標記為守護線程。而Java程序中的初始線程——就是開始于main()的那個,是非守護線程。
  只要還有任何非守護線程在運行,那么這個Java程序也在繼續運行。當該程序中所有的非守護線程都終止時,虛擬機實例將自動退出。假若安全管理器允許,程序本身也能夠通過調用Runtime類或者System類的exit()方法來退出。

JAVA虛擬機的體系結構

下圖是JAVA虛擬機的結構圖,每個Java虛擬機都有一個類裝載子系統,它根據給定的全限定名來裝入類型(類或接口)。同樣,每個Java虛擬機都有一個執行引擎,它負責執行那些包含在被裝載類的方法中的指令。

  

  當JAVA虛擬機運行一個程序時,它需要內存來存儲許多東西,例如:字節碼、從已裝載的class文件中得到的其他信息、程序創建的對象、傳遞給方法的參數,返回值、局部變量等等。Java虛擬機把這些東西都組織到幾個“運行時數據區”中,以便于管理。

  某些運行時數據區是由程序中所有線程共享的,還有一些則只能由一個線程擁有。每個Java虛擬機實例都有一個方法區以及一個堆,它們是由該虛擬機實例中所有的線程共享的。當虛擬機裝載一個class文件時,它會從這個class文件包含的二進制數據中解析類型信息。然后把這些類型信息放到方法區中。當程序運行時,虛擬機會把所有該程序在運行時創建的對象都放到堆中。

  

  當每一個新線程被創建時,它都將得到它自己的PC寄存器(程序計數器)以及一個Java棧,如果線程正在執行的是一個Java方法(非本地方法),那么PC寄存器的值將總是指向下一條將被執行的指令,而它的Java棧則總是存儲該線程中Java方法調用的狀態——包括它的局部變量,被調用時傳進來的參數、返回值,以及運算的中間結果等等。而本地方法調用的狀態,則是以某種依賴于具體實現的方法存儲在本地方法棧中,也可能是在寄存器或者其他某些與特定實現相關的內存區中。
  Java棧是由許多棧幀(stack frame)組成的,一個棧幀包含一個Java方法調用的狀態。當線程調用一個Java方法時,虛擬機壓入一個新的棧幀到該線程的Java棧中,當該方法返回時,這個棧幀被從Java棧中彈出并拋棄。
  Java虛擬機沒有寄存器,其指令集使用Java棧來存儲中間數據。這樣設計的原因是為了保持Java虛擬機的指令集盡量緊湊、同時也便于Java虛擬機在那些只有很少通用寄存器的平臺上實現。另外,Java虛擬機這種基于棧的體系結構,也有助于運行時某些虛擬機實現的動態編譯器和即時編譯器的代碼優化。
  下圖描繪了Java虛擬機為每一個線程創建的內存區,這些內存區域是私有的,任何線程都不能訪問另一個線程的PC寄存器或者Java棧。

  

  上圖展示了一個虛擬機實例的快照,它有三個線程正在執行。線程1和線程2都正在執行Java方法,而線程3則正在執行一個本地方法。
  Java棧都是向下生長的,而棧頂都顯示在圖的底部。當前正在執行的方法的棧幀則以淺色表示,對于一個正在運行Java方法的線程而言,它的PC寄存器總是指向下一條將被執行的指令。比如線程1和線程2都是以淺色顯示的,由于線程3當前正在執行一個本地方法,因此,它的PC寄存器——以深色顯示的那個,其值是不確定的。

數據類型

Java虛擬機是通過某些數據類型來執行計算的,數據類型可以分為兩種:基本類型和引用類型,基本類型的變量持有原始值,而引用類型的變量持有引用值。

  

  Java語言中的所有基本類型同樣也都是Java虛擬機中的基本類型。但是boolean有點特別,雖然Java虛擬機也把boolean看做基本類型,但是指令集對boolean只有很有限的支持,當編譯器把Java源代碼編譯為字節碼時,它會用int或者byte來表示boolean。在Java虛擬機中,false是由整數零來表示的,所有非零整數都表示true,涉及boolean值的操作則會使用int。另外,boolean數組是當做byte數組來訪問的,但是在“堆”區,它也可以被表示為位域。

  Java虛擬機還有一個只在內部使用的基本類型:returnAddress,Java程序員不能使用這個類型,這個基本類型被用來實現Java程序中的finally子句。該類型是jsr, ret以及jsr_w指令需要使用到的,它的值是JVM指令的操作碼的指針。returnAddress類型不是簡單意義上的數值,不屬于任何一種基本類型,并且它的值是不能被運行中的程序所修改的。
  Java虛擬機的引用類型被統稱為“引用(reference)”,有三種引用類型:類類型、接口類型、以及數組類型,它們的值都是對動態創建對象的引用。類類型的值是對類實例的引用;數組類型的值是對數組對象的引用,在Java虛擬機中,數組是個真正的對象;而接口類型的值,則是對實現了該接口的某個類實例的引用。還有一種特殊的引用值是null,它表示該引用變量沒有引用任何對象。

JAVA中方法參數的引用傳遞

java中參數的傳遞有兩種,分別是按值傳遞和按引用傳遞。按值傳遞不必多說,下面就說一下按引用傳遞。
  “當一個對象被當作參數傳遞到一個方法”,這就是所謂的按引用傳遞。

public class User {
    
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
    
}
public class Test {
    
    public void set(User user){
        user.setName("hello world");
    }
    
    public static void main(String[] args) {
        
        Test test = new Test();
        User user = new User();
        test.set(user);
        System.out.println(user.getName());
    }
}

上面代碼的輸出結果是“hello world”,這不必多說,那如果將set方法改為如下,結果會是多少呢?

  public void set(User user){
        user.setName("hello world");
        user = new User();
        user.setName("change");
    }

答案依然是“hello world”,下面就讓我們來分析一下如上代碼。
  首先

User user = new User();

是在堆中創建了一個對象,并在棧中創建了一個引用,此引用指向該對象,如下圖:


User user = new User();

是將引用user作為參數傳遞到set方法,注意:這里傳遞的并不是引用本身,而是一個引用的拷貝。也就是說這時有兩個引用(引用和引用的拷貝)同時指向堆中的對象,如下圖:


user.setName("hello world");

在set()方法中,“user引用的拷貝”操作堆中的User對象,給name屬性設置字符串"hello world"。如下圖:

  
user = new User();

在set()方法中,又創建了一個User對象,并將“user引用的拷貝”指向這個在堆中新創建的對象,如下圖:

  
user.setName("change");

在set()方法中,“user引用的拷貝”操作的是堆中新創建的User對象。


set()方法執行完畢,目光再回到mian()方法

System.out.println(user.getName());

因為之前,"user引用的拷貝"已經將堆中的User對象的name屬性設置為了"hello world",所以當main()方法中的user調用getName()時,打印的結果就是"hello world"。如下圖:

  

歡迎加入學習交流群569772982,大家一起學習交流。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,431評論 6 544
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,637評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 178,555評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,900評論 1 318
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,629評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,976評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,976評論 3 448
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,139評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,686評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,411評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,641評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,129評論 5 364
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,820評論 3 350
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,233評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,567評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,362評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,604評論 2 380

推薦閱讀更多精彩內容

  • JAVA虛擬機的生命周期 一個運行時的Java虛擬機實例的天職是:負責運行一個java程序。當啟動一個Java程序...
    Solang閱讀 1,180評論 0 19
  • 1. Java基礎部分 基礎部分的順序:基本語法,類相關的語法,內部類的語法,繼承相關的語法,異常的語法,線程的語...
    子非魚_t_閱讀 31,737評論 18 399
  • 整天上課都想著玩手機,上課都沒認真聽,真煩,大家不要和我一樣,只想著玩手機。
    ed1a2487f688閱讀 121評論 1 0
  • 我們知道多線程環境下,每一個線程均可以使用所屬進程的全局變量。如果一個線程對全局變量進行了修改,將會影響到其他所有...
    selfboot閱讀 2,624評論 0 5