Java語言引入了Java虛擬機 具有跨平臺運行的功能 能夠很好地適應各種Web應用 同時 為了提高Java語言的性能和健壯性 還引入了如垃圾回收機制等新功能 通過這些改進讓Java具有其獨特的工作原理
成都創(chuàng)新互聯(lián)公司是工信部頒發(fā)資質(zhì)IDC服務器商,為用戶提供優(yōu)質(zhì)的IDC機房托管服務
.Java虛擬機
Java虛擬機(Java Virtual Machine JVM)是軟件模擬的計算機 它可以在任何處理器上(無論是在計算機中還是在其他電子設(shè)備中)安全兼容地執(zhí)行保存在 class文件中的字節(jié)碼 Java虛擬機的 機器碼 保存在 class文件中 有時也可以稱之為字節(jié)碼文件
Java程序的跨平臺特性主要是指字節(jié)碼文件可以在任何具有Java虛擬機的計算機或者電子設(shè)備上運行 Java虛擬機中的Java解釋器負責將字節(jié)碼文件解釋成為特定的機器碼進行運行 因此在運行時 Java源程序需要通過編譯器編譯成為 class文件
Java虛擬機的建立需要針對不同的軟硬件平臺來實現(xiàn) 既要考慮處理器的型號 也要考慮操作系統(tǒng)的種類 由此在SPARC結(jié)構(gòu) X 結(jié)構(gòu) MIPS和PPC等嵌入式處理芯片上 在UNIX Linux Windows和部分實時操作系統(tǒng)上都可實現(xiàn)Java虛擬機
.無用內(nèi)存自動回收機制
在程序的執(zhí)行過程中 部分內(nèi)存在使用過后就處于廢棄狀態(tài) 如果不及時進行回收 很有可能會導致內(nèi)存泄漏 進而引發(fā)系統(tǒng)崩潰 在C++語言中是由程序員進行內(nèi)存回收的 程序員需要在編寫程序時把不再使用的對象內(nèi)存釋放掉 這種人為管理內(nèi)存釋放的方法往往由于程序員的疏忽而致使內(nèi)存無法回收 同時也增加了程序員的工作量 而在Java運行環(huán)境中 始終存在著一個系統(tǒng)級的線程 專門跟蹤內(nèi)存的使用情況 定期檢測出不再使用的內(nèi)存 并自動進行回收 避免了內(nèi)存的泄露 也減輕了程序員的工作量
.代碼安全性檢查機制
安全和方便總是相對矛盾的 Java編程語言的出現(xiàn)使得客戶端計算機可以方便地從網(wǎng)絡上上傳或下載Java程序到本地計算機上運行 但是如何保證該Java程序不攜帶病毒或者沒有其他危險目的呢?為了確保Java程序執(zhí)行的安全性 Java語言通過Applet程序來控制非法程序的安全性 也就是有了它才確保Java語言的生存
Java字節(jié)碼的執(zhí)行需要經(jīng)過以下 個步驟
( )由類裝載器(class loader)負責把類文件( class文件)加載到Java虛擬機中 在此過程需要檢驗該類文件是否符合類文件規(guī)范
( )字節(jié)碼校驗器(bytecode verifier)檢查該類文件的代碼中是否存在著某些非法操作 例如Applet程序中寫本地計算機文件系統(tǒng)的操作
( )如果字節(jié)碼校驗器檢驗通過 由Java解釋器負責把該類文件解釋成為機器碼進行執(zhí)行
注意
Java虛擬機采用 沙箱 運行模式 即把Java程序的代碼和數(shù)據(jù)都限制在一定內(nèi)存空間里執(zhí)行 不允許程序訪問該內(nèi)存空間以外的內(nèi)存 如果是Applet程序 還不允許訪問客戶端機器的文件系統(tǒng)
Java的運行環(huán)境
無論哪種語言都需要有它特定的運行環(huán)境 也就是平臺 Java語言同樣不例外 但是如何理解Java程序與硬件環(huán)境無關(guān)呢?
幾乎所有的語言都需要通過編譯或者解釋才可以被計算機執(zhí)行 但是Java有一點不同 它同時需要這兩個過程 其實 也正是因為這個原因才使Java這種語言具有了平臺無關(guān)性 當完成一個Java源程序后 首先 通過Java翻譯程序?qū)⑺幾g成一種叫做字節(jié)碼的中間代碼 然后再由Java平臺的解釋器將它轉(zhuǎn)換成為機器語言來執(zhí)行 這一平臺的核心就是JVM
Java的編譯過程與其他的語言不同 像C++這樣的語言 在編譯時它是與計算機的硬件平臺信息密不可分的 編譯程序通過查表將所有指令的操作數(shù)和操作碼等轉(zhuǎn)換成內(nèi)存的偏移量 即程序運行時的內(nèi)存分配方式 目的是保證程序正常運行 而Java卻是將指令轉(zhuǎn)換成為一種 class的文件 這種文件不包含硬件的信息 需要執(zhí)行時只要經(jīng)過安裝有JVM的機器進行解釋 創(chuàng)建內(nèi)存分配后再通過查表來確定一條指令所在的地址 這樣就有效地保證了Java的可移植性和安全性
Java平臺具有這樣的特性和它的結(jié)構(gòu)有關(guān) 通常一個程序運行的平臺是一個硬件或者軟件運行的環(huán)境 目前比較流行的是Windows XP Linux Solaris和MacOS Java的平臺不太一樣 它由兩個部分組成 即JVM和應用程序設(shè)計接口
.JVM
JVM是Java平臺的核心 為了讓編譯產(chǎn)生的字節(jié)碼能更好地解釋與執(zhí)行 因此把JVM分成了 個部分 JVM解釋器 指令系統(tǒng) 寄存器 棧 存儲區(qū)和碎片回收區(qū)
◆JVM解釋器 即這個虛擬機處理字段碼的CPU
◆JVM指令系統(tǒng) 該系統(tǒng)與計算機很相似 一條指令由操作碼和操作數(shù)兩部分組成 操作碼為 位二進制數(shù) 主要是為了說明一條指令的功能 操作數(shù)可以根據(jù)需要而定 JVM有多達 種不同的操作指令
◆寄存器 JVM有自己的虛擬寄存器 這樣就可以快速地與JVM的解釋器進行數(shù)據(jù)交換 為了功能的需要 JVM設(shè)置了 個常用的 位寄存器 pc(程序計數(shù)器) optop(操作數(shù)棧頂指針) frame(當前執(zhí)行環(huán)境指針)和vars(指向當前執(zhí)行環(huán)境中第一個局部變量的指針)
◆JVM棧 指令執(zhí)行時數(shù)據(jù)和信息存儲的場所和控制中心 它提供給JVM解釋器運算所需要的信息
◆存儲區(qū) JVM存儲區(qū)用于存儲編譯過后的字節(jié)碼等信息
◆碎片回收區(qū) JVM碎片回收是指將使用過的Java類的具體實例從內(nèi)存進行回收 這就使得開發(fā)人員免去了自己編程控制內(nèi)存的麻煩和危險 隨著JVM的不斷升級 其碎片回收的技術(shù)和算法也更加合理 JVM 版后產(chǎn)生了一種叫分代收集技術(shù) 簡單來說就是利用對象在程序中生存的時間劃分成代 以此為標準進行碎片回收
.Java應用程序設(shè)計接口
Java Application Programming Interface簡稱Java API 其中文名為Java應用程序設(shè)計接口 它是一個軟件集合 其中有許多開發(fā)時所需要的控件 可以用它來輔助開發(fā)
lishixinzhi/Article/program/Java/hx/201311/26733
先要了解java的一個概念———虛擬機(Java Virtual Machine 簡稱JVM),他讓java實現(xiàn)了跨平臺。Java虛擬機在執(zhí)行字節(jié)碼時,把字節(jié)碼解釋成具體平臺上的機器指令執(zhí)行。開發(fā)工具也都是通過jdk編譯執(zhí)行代碼的。例如:myeclipse。
java web開發(fā)也是通過容器(比如tomcat)將java文件編譯,再執(zhí)行生成的代碼,例如:tomcat,它會先將你編寫的jsp文件中的java代碼編譯,編譯后的class文件可以在tomcat的安裝目錄的work文件夾下找到。容器再執(zhí)行這些功能性代碼,再將結(jié)果導入到頁面中去。
JVM工作原理和特點主要是指操作系統(tǒng)裝入JVM是通過jdk中Java.exe來完成,通過下面4步來完成JVM環(huán)境. 1.創(chuàng)建JVM裝載環(huán)境和配置 2.裝載JVM.dll 3.初始化JVM.dll并掛界到JNIENV(JNI調(diào)用接口)實例 4.調(diào)用JNIEnv實例裝載并處理class類。
在我們運行和調(diào)試Java程序的時候,經(jīng)常會提到一個JVM的概念.JVM是Java程序運行的環(huán)境,但是他同時一個操作系統(tǒng)的一個應用程序一個進程,因此他也有他自己的運行的生命周期,也有自己的代碼和數(shù)據(jù)空間. 首先來說一下JVM工作原理中的jdk這個東西,不管你是初學者還是高手,是j2ee程序員還是j2se程序員,jdk總是在幫我們做一些事情.我們在了解Java之前首先大師們會給我們提供說jdk這個東西.它在Java整個體系中充當著什么角色呢?我很驚嘆sun大師們設(shè)計天才,能把一個如此完整的體系結(jié)構(gòu)化的如此完美.jdk在這個體系中充當一個生產(chǎn)加工中心,產(chǎn)生所有的數(shù)據(jù)輸出,是所有指令和戰(zhàn)略的執(zhí)行中心.本身它提供了Java的完整方案,可以開發(fā)目前Java能支持的所有應用和系統(tǒng)程序.這里說一個問題,大家會問,那為什么還有j2me,j2ee這些東西,這兩個東西目的很簡單,分別用來簡化各自領(lǐng)域內(nèi)的開發(fā)和構(gòu)建過程.jdk除了JVM之外,還有一些核心的API,集成API,用戶工具,開發(fā)技術(shù),開發(fā)工具和API等組成
C,編譯是把java文件編譯為class文件,由編譯器完成,jvm執(zhí)行的是class文件,執(zhí)行需要加載,校驗,執(zhí)行……
JDK(Java Development Kit)即為Java開發(fā)工具包,包含編寫Java程序所必須的編譯、運行等開發(fā)工具以及JRE。開發(fā)工具如:用于編譯java程序的javac命令、用于啟動JVM運行java程序的java命令、用于生成文檔的javadoc命令以及用于打包的jar命令等等
JRE(Java Runtime Environment)即為Java運行環(huán)境,提供了運行Java應用程序所必須的軟件環(huán)境,包含有Java虛擬機(JVM)和豐富的系統(tǒng)類庫。系統(tǒng)類庫即為java提前封裝好的功能類,只需拿來直接使用即可,可以大大的提高開發(fā)效率。
JVM(Java Virtual Machines)即為Java虛擬機,提供了字節(jié)碼文件(.class)的運行環(huán)境支持。
JDK、JRE、JVM關(guān)系如圖– 4 所示:
圖- 4
從圖示可以看出,JDK中包含了編譯、運行等開發(fā)工具及JRE,而JRE中包含了Java系統(tǒng)類庫及JVM,運行一個java程序所需要的最小環(huán)境即為JRE,而開發(fā)一個Java程序所需要的最小環(huán)境為JDK,因為JDK中還包含了很多用到的命令。
Java虛擬機(JVM)是可運行Java代碼的假想計算機。只要根據(jù)JVM規(guī)格描述將解釋器移植到特定的計算機上,就能保證經(jīng)過編譯的任何Java代碼能夠在該系統(tǒng)上運行。本文首先簡要介紹從Java文件的編譯到最終執(zhí)行的過程,隨后對JVM規(guī)格描述作一說明。
一.Java源文件的編譯、下載、解釋和執(zhí)行
Java應用程序的開發(fā)周期包括編譯、下載、解釋和執(zhí)行幾個部分。Java編譯程序?qū)ava源程序翻譯為JVM可執(zhí)行代碼?字節(jié)碼。這一編譯過程同C/C++的編譯有些不同。當C編譯器編譯生成一個對象的代碼時,該代碼是為在某一特定硬件平臺運行而產(chǎn)生的。因此,在編譯過程中,編譯程序通過查表將所有對符號的引用轉(zhuǎn)換為特定的內(nèi)存偏移量,以保證程序運行。Java編譯器卻不將對變量和方法的引用編譯為數(shù)值引用,也不確定程序執(zhí)行過程中的內(nèi)存布局,而是將這些符號引用信息保留在字節(jié)碼中,由解釋器在運行過程中創(chuàng)立內(nèi)存布局,然后再通過查表來確定一個方法所在的地址。這樣就有效的保證了Java的可移植性和安全性。
運行JVM字節(jié)碼的工作是由解釋器來完成的。解釋執(zhí)行過程分三部進行:代碼的裝入、代碼的校驗和代碼的執(zhí)行。裝入代碼的工作由"類裝載器"(class loader)完成。類裝載器負責裝入運行一個程序需要的所有代碼,這也包括程序代碼中的類所繼承的類和被其調(diào)用的類。當類裝載器裝入一個類時,該類被放在自己的名字空間中。除了通過符號引用自己名字空間以外的類,類之間沒有其他辦法可以影響其他類。在本臺計算機上的所有類都在同一地址空間內(nèi),而所有從外部引進的類,都有一個自己獨立的名字空間。這使得本地類通過共享相同的名字空間獲得較高的運行效率,同時又保證它們與從外部引進的類不會相互影響。當裝入了運行程序需要的所有類后,解釋器便可確定整個可執(zhí)行程序的內(nèi)存布局。解釋器為符號引用同特定的地址空間建立對應關(guān)系及查詢表。通過在這一階段確定代碼的內(nèi)存布局,Java很好地解決了由超類改變而使子類崩潰的問題,同時也防止了代碼對地址的非法訪問。
隨后,被裝入的代碼由字節(jié)碼校驗器進行檢查。校驗器可發(fā)現(xiàn)操作數(shù)棧溢出,非法數(shù)據(jù)類型轉(zhuǎn)化等多種錯誤。通過校驗后,代碼便開始執(zhí)行了。
Java字節(jié)碼的執(zhí)行有兩種方式:
1.即時編譯方式:解釋器先將字節(jié)碼編譯成機器碼,然后再執(zhí)行該機器碼。
2.解釋執(zhí)行方式:解釋器通過每次解釋并執(zhí)行一小段代碼來完成Java字節(jié)碼程 序的所有操作。
通常采用的是第二種方法。由于JVM規(guī)格描述具有足夠的靈活性,這使得將字節(jié)碼翻譯為機器代碼的工作
具有較高的效率。對于那些對運行速度要求較高的應用程序,解釋器可將Java字節(jié)碼即時編譯為機器碼,從而很好地保證了Java代碼的可移植性和高性能。
二.JVM規(guī)格描述
JVM的設(shè)計目標是提供一個基于抽象規(guī)格描述的計算機模型,為解釋程序開發(fā)人員提很好的靈活性,同時也確保Java代碼可在符合該規(guī)范的任何系統(tǒng)上運行。JVM對其實現(xiàn)的某些方面給出了具體的定義,特別是對Java可執(zhí)行代碼,即字節(jié)碼(Bytecode)的格式給出了明確的規(guī)格。這一規(guī)格包括操作碼和操作數(shù)的語法和數(shù)值、標識符的數(shù)值表示方式、以及Java類文件中的Java對象、常量緩沖池在JVM的存儲映象。這些定義為JVM解釋器開發(fā)人員提供了所需的信息和開發(fā)環(huán)境。Java的設(shè)計者希望給開發(fā)人員以隨心所欲使用Java的自由。
JVM定義了控制Java代碼解釋執(zhí)行和具體實現(xiàn)的五種規(guī)格,它們是:
JVM指令系統(tǒng)
JVM寄存器
JVM棧結(jié)構(gòu)
JVM碎片回收堆
JVM存儲區(qū)
2.1JVM指令系統(tǒng)
JVM指令系統(tǒng)同其他計算機的指令系統(tǒng)極其相似。Java指令也是由 操作碼和操作數(shù)兩部分組成。操作碼為8位二進制數(shù),操作數(shù)進緊隨在操作碼的后面,其長度根據(jù)需要而不同。操作碼用于指定一條指令操作的性質(zhì)(在這里我們采用匯編符號的形式進行說明),如iload表示從存儲器中裝入一個整數(shù),anewarray表示為一個新數(shù)組分配空間,iand表示兩個整數(shù)的"與",ret用于流程控制,表示從對某一方法的調(diào)用中返回。當長度大于8位時,操作數(shù)被分為兩個以上字節(jié)存放。JVM采用了"big endian"的編碼方式來處理這種情況,即高位bits存放在低字節(jié)中。這同 Motorola及其他的RISC CPU采用的編碼方式是一致的,而與Intel采用的"little endian "的編碼方式即低位bits存放在低位字節(jié)的方法不同。
Java指令系統(tǒng)是以Java語言的實現(xiàn)為目的設(shè)計的,其中包含了用于調(diào)用方法和監(jiān)視多先程系統(tǒng)的指令。Java的8位操作碼的長度使得JVM最多有256種指令,目前已使用了160多種操作碼。
2.2JVM指令系統(tǒng)
所有的CPU均包含用于保存系統(tǒng)狀態(tài)和處理器所需信息的寄存器組。如果虛擬機定義較多的寄存器,便可以從中得到更多的信息而不必對?;騼?nèi)存進行訪問,這有利于提高運行速度。然而,如果虛擬機中的寄存器比實際CPU的寄存器多,在實現(xiàn)虛擬機時就會占用處理器大量的時間來用常規(guī)存儲器模擬寄存器,這反而會降低虛擬機的效率。針對這種情況,JVM只設(shè)置了4個最為常用的寄存器。它們是:
pc程序計數(shù)器
optop操作數(shù)棧頂指針
frame當前執(zhí)行環(huán)境指針
vars指向當前執(zhí)行環(huán)境中第一個局部變量的指針
所有寄存器均為32位。pc用于記錄程序的執(zhí)行。optop,frame和vars用于記錄指向Java棧區(qū)的指針。
2.3JVM棧結(jié)構(gòu)
作為基于棧結(jié)構(gòu)的計算機,Java棧是JVM存儲信息的主要方法。當JVM得到一個Java字節(jié)碼應用程序后,便為該代碼中一個類的每一個方法創(chuàng)建一個棧框架,以保存該方法的狀態(tài)信息。每個??蚣馨ㄒ韵氯愋畔ⅲ?/p>
局部變量
執(zhí)行環(huán)境
操作數(shù)棧
局部變量用于存儲一個類的方法中所用到的局部變量。vars寄存器指向該變量表中的第一個局部變量。
執(zhí)行環(huán)境用于保存解釋器對Java字節(jié)碼進行解釋過程中所需的信息。它們是:上次調(diào)用的方法、局部變量指針和操作數(shù)棧的棧頂和棧底指針。執(zhí)行環(huán)境是一個執(zhí)行一個方法的控制中心。例如:如果解釋器要執(zhí)行iadd(整數(shù)加法),首先要從frame寄存器中找到當前執(zhí)行環(huán)境,而后便從執(zhí)行環(huán)境中找到操作數(shù)棧,從棧頂彈出兩個整數(shù)進行加法運算,最后將結(jié)果壓入棧頂。
操作數(shù)棧用于存儲運算所需操作數(shù)及運算的結(jié)果。
2.4JVM碎片回收堆
Java類的實例所需的存儲空間是在堆上分配的。解釋器具體承擔為類實例分配空間的工作。解釋器在為一個實例分配完存儲空間后,便開始記錄對該實例所占用的內(nèi)存區(qū)域的使用。一旦對象使用完畢,便將其回收到堆中。
在Java語言中,除了new語句外沒有其他方法為一對象申請和釋放內(nèi)存。對內(nèi)存進行釋放和回收的工作是由Java運行系統(tǒng)承擔的。這允許Java運行系統(tǒng)的設(shè)計者自己決定碎片回收的方法。在SUN公司開發(fā)的Java解釋器和Hot Java環(huán)境中,碎片回收用后臺線程的方式來執(zhí)行。這不但為運行系統(tǒng)提供了良好的性能,而且使程序設(shè)計人員擺脫了自己控制內(nèi)存使用的風險。
2.5JVM存儲區(qū)
JVM有兩類存儲區(qū):常量緩沖池和方法區(qū)。常量緩沖池用于存儲類名稱、方法和字段名稱以及串常量。方法區(qū)則用于存儲Java方法的字節(jié)碼。對于這兩種存儲區(qū)域具體實現(xiàn)方式在JVM規(guī)格中沒有明確規(guī)定。這使得Java應用程序的存儲布局必須在運行過程中確定,依賴于具體平臺的實現(xiàn)方式。
JVM是為Java字節(jié)碼定義的一種獨立于具體平臺的規(guī)格描述,是Java平臺獨立性的基礎(chǔ)。目前的JVM還存在一些限制和不足,有待于進一步的完善,但無論如何,JVM的思想是成功的。
對比分析:如果把Java原程序想象成我們的C++原程序,Java原程序編譯后生成的字節(jié)碼就相當于C++原程序編譯后的80x86的機器碼(二進制程序文件),JVM虛擬機相當于80x86計算機系統(tǒng),Java解釋器相當于80x86CPU。在80x86CPU上運行的是機器碼,在Java解釋器上運行的是Java字節(jié)碼。
Java解釋器相當于運行Java字節(jié)碼的“CPU”,但該“CPU”不是通過硬件實現(xiàn)的,而是用軟件實現(xiàn)的。Java解釋器實際上就是特定的平臺下的一個應用程序。只要實現(xiàn)了特定平臺下的解釋器程序,Java字節(jié)碼就能通過解釋器程序在該平臺下運行,這是Java跨平臺的根本。當前,并不是在所有的平臺下都有相應Java解釋器程序,這也是Java并不能在所有的平臺下都能運行的原因,它只能在已實現(xiàn)了Java解釋器程序的平臺下運行。