當前位置:菜譜大全網 - 素菜食譜大全 - JVM的原理是什麽?

JVM的原理是什麽?

這裏首先澄清兩個概念:JVM實例和JVM執行引擎實例。JVM實例對應壹個獨立運行的Java程序,而JVM執行引擎實例對應壹個屬於運行程序的用戶的線程。也就是說,JVM實例在進程級,執行引擎在線程級。JVM是什麽?-JVM的生命周期JVM實例的誕生:當壹個Java程序啟動時,會生成壹個JVM實例,任何帶有publistaticvoidmain(string[]args)函數的類都可以作為JVM實例運行的起點。在這種情況下,JVM如何知道它運行的是classA的main而不是classB的main?這就需要明確的告訴JVM類名,也就是我們平時運行Java程序的命令來源,比如JavaclassAhelloworld,其中Java是告訴os運行SunJava2SDK的Java虛擬機,classA指出運行JVM需要的類名。JVM實例的運行:main()是程序初始線程的起點,其他任何線程都是由這個線程啟動的。JVM中有兩種線程:守護線程和非守護線程。main()屬於非守護線程,守護線程通常由JVM自己使用。Java程序也可以指明它們創建的線程是守護線程。JVM實例的死亡:當程序中所有非守護線程終止時,JVM將退出;如果安全管理器允許,程序也可以使用運行時類或System.exit()來退出。JVM是什麽?JVM的架構大致分為三個部分:類加載器子系統、運行時數據區和執行引擎。下面先介紹類加載器,然後是執行引擎,最後是運行時數據區1和類加載器,顧名思義就是用來加載的。類文件。有兩種JVM加載器:啟動類加載器和用戶定義的類加載器。啟動類加載器是JVM實現的壹部分,用戶自定義類加載器是Java程序的壹部分,它必須是class loader類的子類。(以下情況針對SunJDK1.2)動態類加載器:對於要加載的自定義類加載器,只搜索系統類(JavaAPI的類文件)的安裝路徑。系統類加載器:在JVM啟動時創建,用於在類路徑目錄中查找要加載的類。其他用戶定義的類裝入器:有必要先談談類裝入器類的幾種方法,以了解它們是如何被用戶定義的類裝入器裝入的..protectedfinalClassdefineClass(string name,bytedata[],into offset,intlength)protectedfinalClassdefineClass(string name,bytedata[],into offset,int length,ProtectionDomainprotectionDomain);ProtectedDefinedclassFindSystemClass(字符串名)protecteddefinedvidresolveclass(C類)用於將二進制類文件(新類型)導入方法區域。也就是說,這裏所指的類是用戶自定義的類(也就是負責加載類)。findSystemClass通過類型的完全限定名加載,首先通過系統類加載器或啟動類加載器,並返回類對象。ResolveClass:讓類加載器連接(包括驗證、分配內存初始化、將類型中的符號引用解析為直接引用),這就涉及到Java命名空間的問題。JVM保證壹個類加載器加載的壹個類引用的所有類都被這個類加載器加載,同壹個類加載器加載的類可以互相訪問,但不同類加載器加載的類看不到對方,從而實現有效屏蔽。2.執行引擎:它要麽執行字節碼,要麽執行本地方法。要執行引擎,它必須是壹個指令集。每條指令包含壹個單字節操作碼,後跟0個或多個操作數。(1)以棧為設計中心而不是以寄存器為中心的指令集設計如何滿足Java系統的要求?平臺無關性:以棧為中心,更方便在寄存器很少的機器上實現Java。編譯器通常使用堆棧將編譯的中間結果傳遞給連接優化器。如果指令集是基於堆棧的,那麽將運行時的優化工作與執行即時編譯或自適應優化的執行引擎結合起來是有益的。通俗地說,就是讓用於編譯和操作的數據結構統壹起來,更多。網絡移動性:類文件的緊湊性。安全性:指令集中的大多數操作碼指示操作的類型。(加載時利用數據流分析周期進行壹次性驗證,而不是在執行每條指令時進行驗證,有利於提高執行速度)。(二)執行技術主要的執行技術有:解釋、即時編譯、自適應優化、芯片級直接執行,其中解釋屬於第壹代JVM,即時編譯JIT屬於第二代JVM,自適應優化(目前Sun的HotspotJVM采用)借鑒了第壹代JVM和第二代JVM的經驗,采用兩者相結合的方式進行自適應優化:首先解釋並執行所有代碼,然後監控代碼執行。如果不再頻繁使用該方法,編譯後的代碼將被取消,它仍將被解釋和執行。3.運行時數據區:主要包括:方法區、堆、Java棧、PC寄存器、本地方法棧(1)所有線程共享的方法區和堆:運行時存儲所有程序創建的對象的方法區:當JVM的類加載器加載。類文件並解析它,解析後的類型信息被放入方法區域。(2)Java棧和PC寄存器是線程獨占的。在新線程創建期間,(3)本地方法堆棧:存儲本地方法調用的狀態。運行時數據區的主要內容在上面已經大致介紹過了,下面將詳細描述。如果要介紹數據區,就得解釋JVM中的數據類型。JVM中的數據類型:JVM中的基本數據單位是字,字的長度由JVM的具體實現者決定。數據類型包括基本類型和引用類型。(1)基本類型包括:數值型(包括除boolean以外的所有基本Java數據類型)、boolean(在JVM中用int表示,0表示false,其他int值表示true)和返回地址(JVM的內部類型,用來。(2)引用類型包括:數組類型、類類型、接口類型。前面描述了JVM中數據的呈現。我們先來看輸入到JVM的數據區中的方法區:如上所述,方法區主要用於存儲JVM從類文件中提取的類型信息。類型信息是如何存儲的?眾所周知,Java使用big endian (big?Endian:即低字節數據存儲在高級內存中。如果1234,12是高級數據,34是低級數據,那麽Java中的存儲格式應該是12內存低地址,34內存高地址,x86中的存儲格式則相反)來存儲數據。這實際上是數據在類文件中的存儲格式。類型信息:包括類的全限定名、類的直接父類、類類型或接口類型、類的修飾符(public等。),所有直接父接口的列表,並且class對象提供了壹個訪問此信息的窗口(可通過Class.forName(" ")或instance.getClass())獲得)。下面是該類的方法。相信大家會恍然大悟(我看到)getname()、getsuperclass()、isinterface()、getinterfaces()、get class loader();作為類型信息的壹部分,靜態變量保存了對ClassLoader類的引用:動態連接時,它將該類中引用的其他類的引用加載到Class類中:不可避免的,這種類型的常量池上面已經提到:包括直接常量(String、Integer和floatpoint常量)和對其他類型、字段和方法的符號引用(註意:這裏的常量池不是普通意義上的存放常量的地方,這些符號引用可能是我們在編程中接觸到的變量)。因為這些符號引用,這使得常量池成為Java程序動態連接中字段信息至關重要的壹部分:壹般意義上聲明的字段方法信息;類型中每個方法的信息;編譯常數:指的是final聲明的類變量class或者在編譯時用已知值初始化的類變量class,將所有的常數復制到它的常數池或者它的字節流中。方法表:壹個數組,包括其實例可能調用的實例方法的所有直接引用(包括從父類繼承的方法)。另外,如果壹個類不是抽象的,也不是局部的,那麽就要保存方法的字節碼、操作數棧、棧幀和異常表。示例:class lava { privateintspeed = 5;void flow(){ } class volcano { publicstaticvoidmain(String[]args){ lava lava = new lava();lava . flow();}}運行命令JavaVolcano(1)JVM找到Volcano.class,提取對應的類型信息到方法區。通過執行方法區的字節碼,JVM執行main()方法,(執行過程中會壹直保存指向Vocano類常量池的指針)(2)main()中的第壹條指令告訴JVM為常量池第壹項中列出的類分配內存(這裏再次說明常量池並不僅僅存儲常量信息), 然後JVM找到常量池的第壹項,發現是對Lava類的符號引用,於是檢查方法區。 看Lava類是否加載,結果是沒有加載,然後查“Lava.class”,將類型信息寫入方法區,將Volcano原來的常量池中的符號引用替換為指向方法區Lava類信息的指針,也就是將符號引用替換為直接引用。(3)JVM看到new關鍵字,並準備為lava分配內存。根據火山恒常池中的第壹項,找到法域中熔巖的位置,分析需要多少對空間。確認後在堆上分配空間,初始設置速度變量為0,將Lava對象的引用壓入堆棧。(4)調用Lava的flow()方法,大致了解了方法區的內容後,再來看看堆Java對象的堆實現:Java對象主要由實例變量(包括自身類及其父類聲明的變量)、方法區類數據指針、方法表指針、對象鎖(不必要)、等待集合(不必要)、GC相關數據(不必要)(主要取決於GC算法,例如對於mark-and-clear算法,需要標記對象是否被引用、Fin是否被調用)。那麽為什麽Java對象有指向類數據的指針呢?我們從幾個方面考慮:第壹,在程序中將對象引用轉換為另壹種類型時,如何檢查轉換是否被允許?需要類數據。其次,動態綁定時,不需要引用類型,需要運行時類型。這裏的困惑是:為什麽在類數據中保存實際類型而不是引用類型?這個問題我先放壹放。下面的閱讀筆記我想我能理解方法表的指針:類似於C++中的VTBL,有利於提高方法調用的效率:對象鎖:用於實現對多線程共享數據的互斥訪問;它用於使多個線程協調它們的優點和缺點,以達到相同的目標。(註意Object類中的wait()、notify()、notifyAll()方法)。Java數組的堆實現:數組也有壹個與其類相關聯的類實例,具有相同維度和類型的數組是同壹個類的實例。數組類名的表示:如[[LJava/lang/Object表示對象[][],[I表示int[],[[b表示字節[][][][]]到目前為止,堆已經大致介紹完畢。下面介紹壹下程序計數器和Java棧程序計數器:它是每個線程唯壹的,在線程啟動時創建。如果線程執行Java方法,PC保存下壹個。如果thread執行native方法,則Pc的值為undefinedJava stack: Java stack以幀為單位保存線程的運行狀態,Java stack只有兩個操作,即推幀和彈出幀。每個框架代表壹個方法,Java方法有兩種返回方式,return和拋出異常,這兩種方式都會導致方法對應的框架被彈出,釋放內存。框架組成:局部變量區(包括方法參數和局部變量,比如method,這個類型要先保存,其中方法參數嚴格按照聲明順序放置,局部變量可以任意放置)、操作數棧、框架數據區(用來幫助支持常量池的解析、正常方法返回和異常處理)。局部方法棧:這取決於局部方法的實現。例如,如果JVM實現的本地方法使用C連接模型作為借口,則本地方法堆棧就是C堆棧。可以說,當壹個線程調用壹個本地方法時,它進入了壹個不受JVM限制的領域,即JVM可以通過使用本地方法來動態擴展自己。我相信大家都明白JVM是什麽。原文鏈接:blogs . com/趙晨/archive/2011/08/14/2137713 . html