2020国产成人精品视频,性做久久久久久久久,亚洲国产成人久久综合一区,亚洲影院天堂中文av色

分享

Java 虛擬機(jī)體系結(jié)構(gòu)

 燮羽 2011-11-14

眾所周知,Java源代碼被編譯器編譯成class文件。而并不是底層操作系統(tǒng)可以直接執(zhí)行的二進(jìn)制指令(比如Windows OS的.exe文件)。因此,我們需要有一種平臺(tái)可以解釋class文件并運(yùn)行它。而做到這一點(diǎn)的正是Java 虛擬機(jī)(JVM)。

 

實(shí)際上,JVM是一種解釋執(zhí)行class文件的規(guī)范技術(shù)。 個(gè)提 供商都可以根據(jù)規(guī)范,在不同的底層平臺(tái)上實(shí)現(xiàn)不同的JVM。

 

下面是JVM實(shí)現(xiàn)的基本結(jié)構(gòu)框圖。其中類(lèi)裝載子系統(tǒng)、運(yùn)行時(shí)數(shù)據(jù)區(qū)、執(zhí)行引擎 是JVM的必須要解決的幾大問(wèn)題。

 

 
 

★ 類(lèi)裝載器子系統(tǒng) 
在JVM中,類(lèi)裝載器子系統(tǒng)負(fù)責(zé)查找并裝載Class文件。關(guān)于這部分的裝載細(xì)節(jié)詳見(jiàn)《JVM加載class文件的原理 

★ 運(yùn)行時(shí)數(shù)據(jù)區(qū) 
當(dāng)Java虛擬機(jī)運(yùn)行一個(gè)程序時(shí),需要內(nèi)存在存儲(chǔ)許多東西。比如字節(jié)碼,程序創(chuàng)建的對(duì)象,傳遞的方法參數(shù),返回值,局部變量等等。JVM會(huì)把這些東西都組織到幾個(gè)“運(yùn)行時(shí)數(shù)據(jù)區(qū)”中便于管理。
(1) 方法區(qū) 
當(dāng)JVM使用類(lèi)裝載器定位Class文件,并將其輸入到內(nèi)存中時(shí)。會(huì)提取Class文件的類(lèi)型信息,并將這些信息存儲(chǔ)到方法區(qū)中。同時(shí)放入方法取中的還有該類(lèi)型中的類(lèi)靜態(tài)變量。下面我們具體看看需要存儲(chǔ)哪些信息?
●該類(lèi)型的全限定名。如java.io.FileOutputStream
●該類(lèi)型的直接超類(lèi)的全限定名。如java.io.OutputStream
●該類(lèi)型是類(lèi)類(lèi)型還是接口類(lèi)型。
●該類(lèi)型的訪(fǎng)問(wèn)修飾符(public、abstract、final)。
●任何直接超接口的全限定名的有序列表。如java.io.Closeable,  java.io.Flushable。
●該類(lèi)型的常量池。比如所有類(lèi)型、方法和字段的符號(hào)。基本數(shù)據(jù)類(lèi)型的直接數(shù)值等。
●字段信息。對(duì)類(lèi)型中聲明的每個(gè)字段,方法區(qū)中必須保存下面的信息。除此之外,這些字段在類(lèi)或者接口中的聲明順尋也必須保存。

      字段名

      字段的類(lèi)型

      字段的修飾符(public, private, protected, static, final, volatile, transient的某個(gè)子集)

●方法信息。和字段一樣保存方法的相關(guān)信息。

      方法名

      方法的返回類(lèi)型

      方法的參數(shù)的數(shù)量和類(lèi)型

      方法的修飾符

      方法的字節(jié)碼

      操作數(shù)棧和棧幀中局部變量的大小 (見(jiàn)下面Java棧的內(nèi)容)

      異常表
●類(lèi)靜態(tài)變量。這里要注意:類(lèi)中的靜態(tài)變量時(shí)存放在方法區(qū)中的。并不是存放在堆中某一個(gè)該類(lèi)型的對(duì)象中的。 也就是我們常說(shuō)的“類(lèi)靜態(tài)變量屬于類(lèi),而不屬于對(duì)象”這句話(huà)的由來(lái)了。 
●指向ClassLoader類(lèi)的引用。任何類(lèi)都需要被類(lèi)裝載器裝入內(nèi)存。如果是被用戶(hù)自定義類(lèi)裝載器裝載的,那么JVM必須在類(lèi)型信息中存儲(chǔ)對(duì)該裝載器對(duì)象的引用。

●指向Class類(lèi)的 引用。對(duì)于每一個(gè)被裝載的類(lèi)型,虛擬機(jī)都會(huì)相應(yīng)的為它創(chuàng)建一個(gè)java.lang.Class類(lèi)的實(shí)例,而且虛擬機(jī)還必須以某種方式把這個(gè)實(shí)例和存儲(chǔ)在方 法區(qū)中的類(lèi)型信息關(guān)聯(lián)起來(lái)。 這就使得我們可以在程序運(yùn)行時(shí)查看某個(gè)加載進(jìn)內(nèi)存的類(lèi)的當(dāng)前狀態(tài)信息。也就是反射機(jī)制實(shí)現(xiàn)的根本。

●方法表。 為了能快速定位到類(lèi)型中的某個(gè)方法。JVM對(duì)每個(gè)裝載的類(lèi)型都會(huì)建立一個(gè)方法表,用于存儲(chǔ)該類(lèi)型對(duì)象可以調(diào)用的方法的直接引用,這些方法就包括從超類(lèi)中繼 承來(lái)的。而這張表與Java動(dòng)態(tài)綁定機(jī)制( 參見(jiàn)《java動(dòng)態(tài)綁定機(jī)制實(shí)現(xiàn)多態(tài)  )的實(shí)現(xiàn)是密切相關(guān)的。

 

 

方法區(qū)是多線(xiàn)程共享的。也就是當(dāng)虛擬機(jī)實(shí)例開(kāi)始運(yùn)行程序時(shí),邊運(yùn)行邊加載 進(jìn)Class文 件。不同的Class文件都會(huì)提取出不同類(lèi)型信息存放在方法區(qū)中。同樣,方法區(qū)中不再需要運(yùn)行的類(lèi)型信息會(huì)被垃圾回收線(xiàn)程丟棄掉。右圖形象的顯示出了方法區(qū)的樣子。 

 

(2) 堆

Java 程序在運(yùn)行時(shí)創(chuàng)建的所有類(lèi)型對(duì)象和數(shù)組都存儲(chǔ)在堆中。JVM會(huì)根據(jù)new指令在堆中開(kāi)辟一個(gè)確定類(lèi)型的對(duì)象內(nèi)存空間。但是堆中開(kāi)辟對(duì)象的空間并沒(méi)有任何 人工 指令可以回收,而是通過(guò)JVM的垃圾回收器負(fù)責(zé)回收。

 

堆中對(duì)象存儲(chǔ)的是該對(duì)象以及對(duì)象所有超類(lèi)的實(shí)例數(shù)據(jù)(但不是靜態(tài)數(shù)據(jù)), 比如下面的類(lèi)型:

class X{

    private int data;

    private static int stcdata=0;

 

    public X(int d){

         this.data=d;

    }

}

X x1=new X(100);

X x2=new X(200);

這樣在堆中開(kāi)辟了兩個(gè)對(duì)象x1和x2的內(nèi)存空間。其中x1中的一個(gè)實(shí)例數(shù)據(jù)data=100,而x2的data=200。但是這兩個(gè)對(duì)象中都沒(méi)有stcdata這樣的數(shù)據(jù),這個(gè)靜態(tài)數(shù)據(jù)存儲(chǔ)在上面講到的方法區(qū)中。

 

此外,堆中對(duì)象還必須有指向方法區(qū)中的類(lèi)信息數(shù)據(jù)(見(jiàn)上面方法區(qū))。 為什么需要這個(gè)信息呢?因?yàn)楫?dāng)程序在運(yùn)行時(shí)需要對(duì)象轉(zhuǎn)型,那么JVM必須檢查當(dāng)前對(duì)象所屬類(lèi)型及父類(lèi)的信息。以判斷轉(zhuǎn)型是否是合法的,而這一點(diǎn)也是instanceof操作符實(shí)現(xiàn)的基礎(chǔ)。

 

當(dāng)然,上述只是JVM的規(guī)范,具體堆的實(shí)現(xiàn)是由JVM設(shè)計(jì)者來(lái)決定。下面兩幅圖就直觀的表現(xiàn)出了堆對(duì)象的不同實(shí)現(xiàn)結(jié)構(gòu):


其中一個(gè)對(duì)象的引用可能在整個(gè)運(yùn)行時(shí)數(shù)據(jù)區(qū)中的很多地方存在,比如Java棧,堆,方法區(qū)等。

 

堆中對(duì)象還應(yīng)該關(guān)聯(lián)一個(gè)對(duì)象的鎖數(shù)據(jù)信息以及線(xiàn)程的等待集合。 這些都是實(shí)現(xiàn)Java線(xiàn)程同步機(jī)制的基礎(chǔ)。但實(shí)際上很多具體實(shí)現(xiàn)中并不在對(duì)象自身內(nèi)部保存一個(gè)指向鎖數(shù)據(jù)的指針。而只有當(dāng)?shù)谝淮涡枰渔i的時(shí)候才分配對(duì)應(yīng)鎖數(shù)據(jù)。另外,每個(gè)對(duì)象都會(huì)從Object中繼承三個(gè)Object方法(wait、notify、notifyAll),當(dāng)某個(gè)線(xiàn)程在一個(gè)對(duì)象上調(diào)用了等待方法時(shí)。JVM就會(huì)阻塞這個(gè)線(xiàn)程,并把這個(gè)線(xiàn)程放在該對(duì)象的等待集合中。知道另外一個(gè)線(xiàn)程在該對(duì)象上調(diào)用了notify/notifyAll,JVM才會(huì)在等待集合中喚醒一個(gè)或全部的等待線(xiàn)程(參見(jiàn)《正確理解線(xiàn)程等待和釋放(wait/notify)》)。

 

【數(shù)組對(duì)象】

在Java中,數(shù)組也是對(duì)象,那么自然在堆中會(huì)存儲(chǔ)數(shù)組的信息。事實(shí)也確實(shí)如此,對(duì)于JVM而言,數(shù)組與其他類(lèi)對(duì)象沒(méi)有任何區(qū)別。

數(shù)組也有屬于的類(lèi)Class,具有相同維度和類(lèi)型的數(shù)組都是同一個(gè)類(lèi)的實(shí)例,而不管數(shù)組的長(zhǎng)度是多少。

數(shù)組類(lèi)的名稱(chēng)由兩部分構(gòu)成:(1)每一維用一個(gè)方括號(hào)“[”表示。(2) 用字符或字符串表示元素類(lèi)型。比如一維數(shù)組對(duì)象int[] a所屬類(lèi)型名為"[I",二維數(shù)組對(duì)象byte[] b所屬類(lèi)型名為"[[B"。

下圖是二維數(shù)組對(duì)象在堆中的具體實(shí)現(xiàn)方式:

 

 

(3) 程序計(jì)數(shù)器

 

對(duì)于一個(gè)運(yùn)行的Java而言,每一個(gè)線(xiàn)程都有一個(gè)PC寄存器。當(dāng)線(xiàn)程執(zhí)行Java程序時(shí),PC寄存器的內(nèi)容總是下一條將被執(zhí)行的指令地址。

 

(4) Java棧 -  棧幀

 

每啟動(dòng)一個(gè)線(xiàn)程,JVM都會(huì)為它分配一個(gè)Java棧,用于存放方法中的局部變量,操作數(shù)以及異常數(shù)據(jù)等。當(dāng)線(xiàn)程調(diào)用某個(gè)方法時(shí),JVM會(huì)根據(jù)方法區(qū)中該方法的字節(jié)碼組建一個(gè)棧幀。并將該棧幀壓入Java棧中,方法執(zhí)行完畢時(shí),JVM會(huì)彈出該棧幀并釋放掉。

注意,Java棧中的數(shù)據(jù)是線(xiàn)程私有的,一個(gè)線(xiàn)程是無(wú)法訪(fǎng)問(wèn)另一個(gè)線(xiàn)程的Java棧的數(shù)據(jù)。這也就是為什么多線(xiàn)程編程時(shí),兩個(gè)相同線(xiàn)程執(zhí)行同一方法時(shí),對(duì)方法內(nèi)的局部變量時(shí)不需要數(shù)據(jù)同步的原因。

 

棧幀 

棧幀有三部分構(gòu)成:局部變量區(qū)、操作數(shù)棧和幀數(shù)據(jù)區(qū)。在編譯器編譯Java代碼時(shí),就已經(jīng)在字節(jié)碼中為每個(gè)方法都設(shè)置好了局部變量區(qū)和操作數(shù)棧的數(shù)據(jù)和大小。并在JVM首次加載方法所屬的Class文件時(shí),就將這些數(shù)據(jù)放進(jìn)了方法區(qū)。因此在線(xiàn)程調(diào)用方法時(shí),只需要根據(jù)方法區(qū)中的局部變量區(qū)和操作數(shù)棧的大小來(lái)分配一個(gè)新的棧幀的內(nèi)存大小,并堆入Java棧。

 

局部變量區(qū): 用來(lái)存放方法中的所有局部變量值,包括傳遞的參數(shù)。這些數(shù)據(jù)會(huì)被組織成以一個(gè)字長(zhǎng)(32bit或64bit)為單位的數(shù)組結(jié)構(gòu)(以索引0開(kāi)始)中。其中類(lèi)型為int, float, reference(引用類(lèi)型,記錄對(duì)象在堆中地址)和returnAddress(一種JVM內(nèi)部使用的基本類(lèi)型)的值占用1個(gè)字長(zhǎng),而byte, char和shot會(huì)擴(kuò)大成1個(gè)字長(zhǎng)存儲(chǔ),long,double則使用2個(gè)字長(zhǎng)。

 

操作數(shù)棧: 用來(lái)在執(zhí)行指令的時(shí)候存儲(chǔ)和使用中間結(jié)果數(shù)據(jù)。

 

幀數(shù)據(jù)區(qū): 常量池的解析,正常方法返回以及異常派發(fā)機(jī)制的信息數(shù)據(jù)都存儲(chǔ)在其中。

 

下圖展示了addAndPrint()調(diào)用addTwoTypes()時(shí),Java棧的變化:

 

★ 執(zhí)行引擎

運(yùn)行Java的每一個(gè)線(xiàn)程都是一個(gè)獨(dú)立的虛擬機(jī)執(zhí)行引擎的實(shí)例。從線(xiàn)程生命周期的開(kāi)始到結(jié)束,他要么在執(zhí)行字節(jié)碼,要么在執(zhí)行本地方法。一個(gè)線(xiàn)程可能通過(guò)解釋或者使用芯片級(jí)指令直接執(zhí)行字節(jié)碼,或者間接通過(guò)JIT執(zhí)行編譯過(guò)的本地代碼。

 

指令集: 實(shí)際上,Class文件中方法的字節(jié)碼流就是有JVM的指令序列構(gòu)成的。每一條指令包含一個(gè)單字節(jié)的操作碼,后面跟隨0個(gè)或多個(gè)操作數(shù)。

 

Java虛擬機(jī)指令集關(guān)注的中心是操作數(shù)棧和局部變量集合。我們可以看看下面一組指令在執(zhí)行引擎中執(zhí)行的過(guò)程:

Jvm助記指令代碼  收藏代碼
  1. iload_0    // 把存儲(chǔ)在局部變量區(qū)中索引為0的整數(shù)壓入操作數(shù)棧。  
  2. iload_1    // 把存儲(chǔ)在局部變量區(qū)中索引為1的整數(shù)壓入操作數(shù)棧。  
  3. iadd         // 從操作數(shù)棧中彈出兩個(gè)整數(shù)相加,在將結(jié)果壓入操作數(shù)棧。  
  4. istore_2   // 從操作數(shù)棧中彈出結(jié)果  

很顯然,上面的指令反復(fù)用到了Java棧中的某一個(gè)方法棧幀。實(shí)際上執(zhí)行引擎運(yùn)行Java字節(jié)碼指令很多時(shí)候都是在不停的操作Java棧,也有的時(shí)候需要在堆中開(kāi)辟對(duì)象以及運(yùn)行系統(tǒng)的本地指令等。但是Java棧的操作要比堆中的操作要快的多,因此反復(fù)開(kāi)辟對(duì)象是非常耗時(shí)的。這也是為什么Java程序優(yōu)化的時(shí)候,盡量減少new對(duì)象。

 

 

 

 

下面將會(huì)是很有趣的過(guò)程,我們用一段代碼來(lái)生動(dòng)的展現(xiàn)JVM是如何運(yùn)行這段程序的。

 

通過(guò)編譯器將下面的代碼編譯成edu/hr/jvm/Test.class 和 edu/hr/jvm/bean/Act.class。然后開(kāi)始啟動(dòng)JVM:

Java代碼  收藏代碼
  1. //源代碼 Test.java  
  2. package edu.hr.jvm;  
  3.   
  4. import edu.hr.jvm.bean;  
  5. public class Test{  
  6.        public static void main(String[] args){  
  7.                Act act=new Act();  
  8.                act.doMathForever();  
  9.        }  
  10. }  
  11.   
  12. //源代碼 Act.java  
  13. package edu.hr.jvm.bean;  
  14.   
  15. public class Act{  
  16.        public void doMathForever(){  
  17.               int i=0;  
  18.               for(;;){  
  19.                      i+=1;  
  20.                      i*=2;   
  21.               }  
  22.        }  
  23. }  

 

(1) 首先OS會(huì)創(chuàng)建一個(gè)JVM實(shí)例(進(jìn)行必要的初始化工作,比如初始啟動(dòng)類(lèi)裝載器,初始運(yùn)行時(shí)內(nèi)存數(shù)據(jù)區(qū)等)。

 

(2) 然后通過(guò)自定義類(lèi)裝載器 加載Test.class。并提取Test.class字節(jié)碼中的信息存放在方法區(qū) 中(具體的信息在上面已經(jīng)講過(guò))。右圖展示了方法區(qū)中的Test類(lèi)信息,其中在常量池中有一個(gè)符號(hào)引用"Act"(注意:這個(gè)引用目前還沒(méi)有真正的類(lèi)信息 的內(nèi)存地址)。

 

(3) 接著JVM開(kāi)始從Test類(lèi)的main字節(jié)碼處開(kāi)始解釋執(zhí)行。在運(yùn)行之前,會(huì)在Java棧中組建一個(gè)main方法的棧幀 。如右圖Java棧所示。JVM需要運(yùn)行任何方法前,通過(guò)在Java棧 中壓入一個(gè)幀棧。在這個(gè)幀棧的內(nèi)存區(qū)域中進(jìn)行計(jì)算。

 

(4) 現(xiàn)在可以開(kāi)始執(zhí)行main方法的第一條指令——JVM需要為常量池 的第一項(xiàng)的類(lèi)(符號(hào)引用Act)分配內(nèi)存空間。但是Act類(lèi)此時(shí)還沒(méi)有加載進(jìn)JVM(因?yàn)槌A砍啬壳爸挥幸粋€(gè)"Act"的符號(hào)引用)。

 

(5) JVM加載進(jìn)Act.class,并提取Act類(lèi)信息 放入方法區(qū)中。見(jiàn)上圖方法區(qū)所示,然后以一個(gè)直接指向方法區(qū)Act類(lèi)信息的直接引用替換開(kāi)始在常量池中的符號(hào)引用"Act",這個(gè)過(guò)程就是常量池解析 。以后就可以直接訪(fǎng)問(wèn)Act的類(lèi)信息了。

 

(6) 此時(shí)JVM可以根據(jù)方法區(qū)中的Act類(lèi)信息,在堆中開(kāi)辟一個(gè)Act類(lèi)對(duì)象 act。見(jiàn)上圖堆所示。

 

(7) 接著開(kāi)始執(zhí)行main方法中的第二條指令調(diào)用doMathForever。這個(gè)可以通過(guò)堆中act對(duì)象所指的方法表 中查找,然后定位到方法區(qū)中的Act類(lèi)信息中的doMathForever方法字節(jié)碼。在運(yùn)行之前,仍然要組建一個(gè)doMathForever棧幀壓入Java棧,如上圖所示。(注意:JVM會(huì)根據(jù)方法區(qū)中doMathForever的字節(jié)碼來(lái)創(chuàng)建棧幀的局部變量區(qū)和操作數(shù)棧的大小)

 

(8) 接下來(lái)JVM開(kāi)始解釋運(yùn)行Act.doMathForever字節(jié)碼的內(nèi)容了。下面我們?cè)敿?xì)的描述一下這個(gè)JVM的運(yùn)行過(guò)程:

● 我們首先看一下doMathForever方法的字節(jié)碼在方法區(qū)中的指令如右圖,其中bytecode是指令的二進(jìn)制編碼 ,mnemonic是指令助記符 ,pc為程序計(jì)數(shù)器 (指向當(dāng)前運(yùn)行指令的下一條),offset為指令存放在方法區(qū)中的地址偏移 。

 

●然后在上面的圖Java棧中已經(jīng)顯示出了doMathForever方法的棧幀,其中比較重要的兩個(gè)部分是局部變量區(qū) 操作數(shù)棧 。而此時(shí)在運(yùn)行指令之前,局部變量區(qū)中只有一個(gè)整型i 的存儲(chǔ)位置(1個(gè)字長(zhǎng))。而操作數(shù)棧中還沒(méi)有被創(chuàng)建了2個(gè)字長(zhǎng)的大小(存儲(chǔ)大小是幀棧創(chuàng)建的時(shí)候由方法區(qū)中的數(shù)據(jù)確定的)。

 

                             局部變量區(qū)

             index        hex value        value

  (變量i)      0                                                

 

 optop: 0                 操作數(shù)棧          

              offset        hex value        value

 optop->    0

                  1

 

 

●  下面運(yùn)行每一條指令后,看一下局部變量區(qū)和操作數(shù)棧的變化:

    ① 指令[iconst_0]   將int類(lèi)型變量的數(shù)據(jù)0壓入操作數(shù)棧。

                             局部變量區(qū)                                                                  操作數(shù)棧     

             index        hex value        value                                 offset        hex value        value

   (變量i)     0                                                                                  0           00000000          0

                                                                                   optop->    1

    ② 指令[istore_0]    彈出操作數(shù)棧頂?shù)臄?shù)據(jù)0,將結(jié)果存儲(chǔ)在局部變量區(qū)中index=0的空間中。

                             局部變量區(qū)                                                                  操作數(shù)棧     

             index        hex value        value                                 offset        hex value        value

   (變量i)     0            00000000          0                          optop->   0 

                                                                                                    1

    ③指令[iinc 0 1]  把常量值1加到局部變量區(qū)中index=0的空間上。

                              局部變量區(qū)                                                                  操作數(shù)棧     

             index        hex value        value                                 offset        hex value        value

   (變量i)     0            00000001          1                          optop->   0 

                                                                                                    1

    ④指令[iload_0]  把局部變量區(qū)index=0中的數(shù)據(jù)堆入操作數(shù)棧。

                              局部變量區(qū)                                                                  操作數(shù)棧     

             index        hex value        value                                 offset        hex value        value

   (變量i)     0            00000001          1                                          0         00000001          1

                                                                                     optop->   1

    ⑤指令[iconst_2] 把int類(lèi)型變量的數(shù)據(jù)2壓入操作數(shù)棧。

                               局部變量區(qū)                                                                  操作數(shù)棧     

             index        hex value        value                                 offset        hex value        value

   (變量i)     0            00000001          1                                          0         00000001          1

                                                                                                    1         00000002           2

                                                                                     optop->

    ⑥指令[imul]  彈出操作數(shù)棧中的兩個(gè)數(shù)據(jù)1和2,相乘之后的結(jié)果2堆入操作數(shù)棧

                               局部變量區(qū)                                                                  操作數(shù)棧     

             index        hex value        value                                 offset        hex value        value

   (變量i)     0            00000001          1                           optop->   0         00000002           2

                                                                                                    1      

     ⑦指令[istore_0]  彈出操作數(shù)棧頂?shù)臄?shù)據(jù)2,將結(jié)果存儲(chǔ)在局部變量區(qū)中index=0的空間中。

                               局部變量區(qū)                                                                  操作數(shù)棧     

             index        hex value        value                                 offset        hex value        value

   (變量i)     0            00000002          2                           optop->   0         

                                                                                                    1     

     ⑧指令[goto 2]   跳轉(zhuǎn)到指令iinc 0 1處循環(huán)執(zhí)行下去.....

 

當(dāng)然,這個(gè)例子不停的執(zhí)行下去只會(huì)出現(xiàn)算術(shù)溢出,也就是一個(gè)字長(zhǎng)(2bytes)的整型變量i 無(wú)法表示不停計(jì)算的結(jié)果了。但是JVM不會(huì)拋出任何異常,

 

 

附:在《深入Java虛擬機(jī)》一書(shū)第5章節(jié)有一個(gè)JVM模擬運(yùn)行上面程序的源代碼和applet展示,做的很不錯(cuò)。下面是這本書(shū)的配到源代碼,大家可以學(xué)習(xí)一下。

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶(hù)發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶(hù) 評(píng)論公約

    類(lèi)似文章 更多