「這里的虛擬機(jī)不是模擬完整硬件的虛擬機(jī),這里主要了解的是JVM與DVM的架構(gòu),它們執(zhí)行的是字節(jié)碼。」
虛擬機(jī)的設(shè)計(jì)架構(gòu)有兩種: 基于求值棧、基于寄存器,如果從更大的范圍可以認(rèn)為只要實(shí)現(xiàn)了功能的都可以認(rèn)為是虛擬機(jī),通過直接遍歷AST得到結(jié)果的也可以算一種虛擬機(jī)。
「基于AST」 的虛擬機(jī)是通過后序遍歷AST節(jié)點(diǎn),利用調(diào)用棧遞歸的對(duì)AST求值,它的特點(diǎn)就是實(shí)現(xiàn)更簡(jiǎn)單,利用更低級(jí)語言或者自身來實(shí)現(xiàn)。
「基于求值堆?!?/strong> 的虛擬機(jī)是零地址指令設(shè)計(jì)的一個(gè)很好的實(shí)踐,它的操作數(shù)是隱藏在棧頂?shù)?利用了棧的先進(jìn)后出的特點(diǎn)實(shí)現(xiàn)了運(yùn)算的優(yōu)先級(jí),相對(duì)比寄存器方案他的指令數(shù)量更多,但是空間占用更低。
「基于虛擬寄存器」 的虛擬機(jī)可以是二地址或者三地址設(shè)計(jì),操作數(shù)存放在虛擬寄存器中,很多指令只需要對(duì)寄存器進(jìn)行讀取,不涉及到速度慢了很多的內(nèi)存,相對(duì)于求值棧的方案,指令數(shù)量更少,空間占用更高。
「有圖有真相」
下面我們來看一段非常簡(jiǎn)單的Java代碼,直觀的感受一下求值棧與寄存器方案的差異。
class Test {
public static void foo() {
int a = 1;
int b = 2;
int c = (a + b) * 5;
}
}
「求值棧寄存器」
這個(gè)程序很簡(jiǎn)單,使用javac
將它編譯成字節(jié)碼,再利用javap查看指令
javac Test.java
javap -v Test
得到如下指令:
接下來,通過觀察指令執(zhí)行流程了解JVM基于棧的邏輯:
可以看出,基于求值棧的VM在執(zhí)行的時(shí)候會(huì)反復(fù)的對(duì)棧進(jìn)行push與pop的操作,這樣一來需要執(zhí)行的指令條數(shù)就多了。
當(dāng)然,上面的指令是未優(yōu)化的,實(shí)際上在生成指令之前可以將a與b直接優(yōu)化掉(常數(shù)折疊),減少內(nèi)存占用。
「寄存器虛擬機(jī)」
同樣是執(zhí)行Java代碼, android 的Dalvik VM是采用基于寄存器的架構(gòu),通過以下命令:
dx --dex --no-optimize --output Test.dex Test.class
如果不顯示的指定--no-optimize,生成的Test.dex經(jīng)過優(yōu)化后,foo函數(shù)里面所有的變量與運(yùn)算都被優(yōu)化掉了,只剩下一個(gè)return-void
指令,從上下文分析可以得出foo內(nèi)部的a,b,c變量與其參與的運(yùn)算都可以不需要。不經(jīng)過優(yōu)化的指令如下:
指令執(zhí)行流程如下:
編譯期已經(jīng)確定棧幀的虛擬寄存器的數(shù)量,v3 v4是加載數(shù)據(jù)與運(yùn)算時(shí)使用的寄存器,v0 v1 v2則對(duì)面最后三個(gè)變量。
數(shù)據(jù)一量裝入寄存器,在盡可能不使用內(nèi)存的情況下只使用寄存器速度快得多,因?yàn)樗挥妙l繁與內(nèi)存打交道了。
任何事物都有兩面性,棧相比寄存器架構(gòu)它的可移植性更強(qiáng),棧在任何機(jī)器上實(shí)現(xiàn)都很容易。在java設(shè)計(jì)之初就希望它是一個(gè)能在所有平臺(tái)上通吃的語言,所以JVM基于棧。
而寄存器架構(gòu)的VM往往會(huì)把虛擬寄存器與實(shí)際的寄存器映射,如果虛擬寄存器的數(shù)量小于等于實(shí)際的寄存器,則實(shí)現(xiàn)起來相對(duì)容易,如果虛擬寄存器數(shù)量大于了實(shí)際的寄存器數(shù)量則相對(duì)復(fù)雜。
Dalvik只用于android平臺(tái),性能往往是更需要關(guān)注的東西,這樣來講android 4.0x開始基于寄存器的DVM就可以理解了,此時(shí)的設(shè)備內(nèi)存普遍高而且CPU的寄存器數(shù)量也多。
「總結(jié):」 棧與寄存器架構(gòu)各有優(yōu)劣,任何的事物在設(shè)計(jì)之初都有它考慮的重點(diǎn),它們沒有絕對(duì)的優(yōu)劣,如果你要用AST來實(shí)現(xiàn)運(yùn)算,只要滿足了你的要求,無可厚非。
好比時(shí)間與空間在寫的程序里永遠(yuǎn)是一個(gè)矛盾的存在,人們總是在追求一個(gè)極致的平衡點(diǎn)。
如果你覺得文章對(duì)你有幫助,可以分享給更多的人或者點(diǎn)在看
。
-
寄存器
+關(guān)注
關(guān)注
31文章
5403瀏覽量
122947 -
虛擬機(jī)
+關(guān)注
關(guān)注
1文章
958瀏覽量
28926 -
AST
+關(guān)注
關(guān)注
0文章
7瀏覽量
2372
發(fā)布評(píng)論請(qǐng)先 登錄
VM下虛擬機(jī)與主機(jī)不能互ping通
請(qǐng)問QTE可以同幾種JAVA虛擬機(jī)集成
Java虛擬機(jī)介紹
Java虛擬機(jī)向ARM平臺(tái)的移植
Java虛擬機(jī)向ARM平臺(tái)的移植
微軟java虛擬機(jī)下載
JAVA虛擬機(jī)的體系結(jié)構(gòu)及基本類型

Java虛擬機(jī)參數(shù)調(diào)優(yōu)
由淺入深的了解Java虛擬機(jī)
Java:JVM虛擬機(jī)的入門知識(shí)

評(píng)論