1.Java代碼有很多 不同的運行方式
1)可以在開發工具中運行
2)可以雙擊執行jar文件運行,
3)也可以在命令行中運行
4)甚至可以在網頁中運行
這些執行方式都離不開JRE ,也就是Java的運行環境。JRE僅包含運行Java程序的必須組件,包括Java虛擬機以及Java核心類庫。Java程序員經常接觸到的JDK同樣包含JRE,並且還附帶了一些開發、診斷工具
2.為什么Java要在虛擬機里運行
Java作為一門高級程序語言,他的語法非常復雜,抽象程度也很高。直接在硬件上運行這種復雜的程序並不現實。所以在運行Java程序之前,我們需要進行一番轉化。
這個轉化具體是怎么操作的呢?
當前的主流思想,就是設計一個面向Java語言特性的虛擬機,並通過編譯器將Java程序轉換成哎虛擬機所能識別的指令序列,也稱為Java字節碼。(Java字節碼指令的操作碼opcode被固定為一個字節)。
Java =寫的helloword程序編譯而成 的字節碼。都是一個個字節組成的
# 最左列是偏移;中間列是給虛擬機讀的機器碼;最右列是給人讀的代碼 0x00: b2 00 02 getstatic java.lang.System.out 0x03: 12 03 ldc "Hello, World!" 0x05: b6 00 04 invokevirtual java.io.PrintStream.println 0x08: b1 return
Java 虛擬機可以由硬件實現 [1],但更為常見的是在各個現有平台(如windows、liunx)上提供軟件實現。這樣做的意義就是,一旦一個程序被轉換成Java 字節碼,那么他便可以在不同平台上的虛擬機實現運行。(一次編寫,到處運行)。
虛擬機的另外一個好處是他帶來了一個托管環境(Managed Runtime)。他能夠代替我們處理一些代碼中的冗長而容易出錯的部分。其中最廣為人知的內存管理和垃圾回收。除此之外還提供了數組越界、動態類型、安全權限等動態檢測,是我們免於書寫這些無關業務邏輯的代碼。
3.Java虛擬機具體是怎樣運行Java字節碼的
執行Java代碼首先需要將他編譯成class文件加載到Java虛擬機中。加載后的Java類會被存放於方法區(method area).實際運行時,虛擬機會執行方法區內的代碼。Java虛擬機同樣會在內存中划分出堆和棧來存儲運行時數據。
在運行過程當中,每當調用一個Java方法,Java虛擬機會在當前線程的Java方法棧中生產一個棧幀。用於存放局部變量以及字節碼的操作數。這個棧幀大小是提前計算好的,而且棧幀在內存空間里可以不是連續分布的。
當退出當前執行的方法時,不管是正常返回還是異常返回,虛擬機均會彈出當前線程的當前棧幀,並將之舍去。
Java字節碼是無法執行的。因此,Java虛擬機需要將字節碼翻譯成機器碼。在hotspot里面,有兩種編譯方式:第一種是解釋執行,逐條將字節碼翻譯成機器碼並執行;第二種是即時編譯,講一個方法中包含的所有字節碼編譯成機器碼后執行。
前者的優勢在於無需等待編譯,而后者的優勢在於實際運行速度更快。hotspot默認采用混合模式,綜合了解執行和即使編譯兩者的優點。他先解釋執行字節碼,而后將其中反復執行的熱點代碼,以方法為單位進行即時編譯。
4.Java虛擬機的運行效率究竟如何
HotSpot采用了多種技術來提升啟動性能以及峰值性能,即時編譯便是其中最終要的技術之一。即時編譯建立在程序符合二八定律的假設上,也即是百分之二十的代碼占據了百分之八十的計算機資源。
對於大部分的不常用的代碼,我們無需耗費時間將其編譯成機器碼,而是采取解釋執行的方式運行;另一方面對於僅占據小部分的帶點代碼,我們則可以將其編譯成機器碼,已達到理想的運行速度。
5.總結
之所以要在虛擬機中運行,是他提供了可移植性。一旦Java代碼被編譯成Java字節碼,變可以在不同平台上運行,虛擬機還提供了一個代碼托管環境,代替我們處理部分冗長的代而且容易出錯的事務。
Java虛擬機將運行時內存區域划分為五個部分,分別為方法區、堆、pc寄存器、Java方法棧和本地方法棧。Java程序編譯而成的calss文件,需要先加載至方法區中,Java虛擬機才能運行。
為了提高效率,標准jdk中的hotspot虛擬機采用的是一種混合執行的策略。他會解釋執行Java字節碼,然后會將其中反復執行的熱點代碼,以方法為單位進行即時編譯,編譯成機器碼后直接運行在底層硬件之上。