JAVA虛擬機工作原理_第1頁
JAVA虛擬機工作原理_第2頁
JAVA虛擬機工作原理_第3頁
JAVA虛擬機工作原理_第4頁
JAVA虛擬機工作原理_第5頁
已閱讀5頁,還剩29頁未讀, 繼續免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

淘寶技術大學應屆生培訓

JVM任務原理課程組:雷卷小邪九穆版本:第一版2021年到達的目的知道Java虛擬機的生存周期知道JVM的體系構造知道JVM體系構造中的各個部分能對JVM有個大致明晰的了解內容JVM的生命周期JVM的體系構造JVM類加載器JVM執行引擎JVM運轉時數據區JVM渣滓回收問題JVM的生命周期

一、首先分析兩個概念JVM實例和JVM執行引擎實例〔1〕JVM實例對應了一個獨立運轉的java程序它是進程級別〔2〕JVM執行引擎實例那么對應了屬于用戶運轉程序的線程它是線程級別的JVM的生命周期

二、JVM的生命周期〔1〕JVM實例的誕生當啟動一個Java程序時,一個JVM實例就產生了,任何一個擁有publicstaticvoidmain(String[]args)函數的class都可以作為JVM實例運轉的起點〔2〕JVM實例的運轉main()作為該程序初始線程的起點,任何其他線程均由該線程啟動。JVM內部有兩種線程:守護線程和非守護線程,main()屬于非守護線程,守護線程通常由JVM本人運用,java程序也可以標明本人創建的線程是守護線程。

〔3〕JVM實例的消亡當程序中的一切非守護線程都終止時,JVM才退出;假設平安管理器允許,程序也可以運用Runtime類或者System.exit()來退出。

內容JVM的生命周期JVM的體系構造JVM類加載器JVM執行引擎JVM運轉時數據區JVM渣滓回收問題JVM的體系構造

JVM的體系構造一、JVM的內部體系構造分為三部分,〔1〕類裝載器〔ClassLoader〕子系統作用:用來裝載.class文件〔2〕執行引擎作用:執行字節碼,或者執行本地方法

〔3〕運轉時數據區方法區,堆,java棧,PC存放器,本地方法棧

內容JVM的生命周期JVM的體系構造JVM類加載器JVM執行引擎JVM運轉時數據區JVM渣滓回收問題JVM的體系構造之類加載器一、JVM將整個類加載過程劃分為了三個步驟:〔1〕裝載裝載過程擔任找到二進制字節碼并加載至JVM中,JVM經過類名、類所在的包名經過ClassLoader來完成類的加載,同樣,也采用以上三個元素來標識一個被加載了的類:類名+包名+ClassLoader實例ID?!?〕鏈接鏈接過程擔任對二進制字節碼的格式進展校驗、初始化裝載類中的靜態變量以及解析類中調用的接口、類。在完成了校驗后,JVM初始化類中的靜態變量,并將其值賦為默許值。最后一步為對類中的一切屬性、方法進展驗證,以確保其需求調用的屬性、方法存在,以及具備應的權限〔例如public、private域權限等〕,會呵斥NoSuchMethodError、NoSuchFieldError等錯誤信息。〔3〕初始化初始化過程即為執行類中的靜態初始化代碼、構造器代碼以及靜態屬性的初始化,在四種情況下初始化過程會被觸發執行:調用了new;反射調用了類中的方法;子類調用了初始化;JVM啟動過程中指定的初始化類。JVM的體系構造之類加載器JVM的體系構造之類加載器一、JVM兩種類裝載器包括:啟動類裝載器和用戶自定義類裝載器,啟動類裝載器是JVM實現的一部分,用戶自定義類裝載器那么是Java程序的一部分,必需是ClassLoader類的子類。二、主要分為以下幾類:(1)BootstrapClassLoader這是JVM的根ClassLoader,它是用C++實現的,JVM啟動時初始化此ClassLoader,并由此ClassLoader完成$JAVA_HOME中jre/lib/rt.jar〔SunJDK的實現〕中一切class文件的加載,這個jar中包含了java規范定義的一切接口以及實現。(2)ExtensionClassLoaderJVM用此classloader來加載擴展功能的一些jar包(3)SystemClassLoaderJVM用此classloader來加載啟動參數中指定的Classpath中的jar包以及目錄,在SunJDK中ClassLoader對應的類名為AppClassLoader。(4)User-DefinedClassLoaderUser-DefinedClassLoader是Java開發人員承繼ClassLoader籠統類自行實現的ClassLoader,基于自定義的ClassLoader可用于加載非Classpath中的jar以及目錄JVM的體系構造之類加載器三、ClassLoader籠統類提供了幾個關鍵的方法:〔1〕loadClass此方法擔任加載指定名字的類,ClassLoader的實現方法為先從曾經加載的類中尋覓,如沒有那么繼續從parentClassLoader中尋覓,如依然沒找到,那么從SystemClassLoader中尋覓,最后再調用findClass方法來尋覓,如要改動類的加載順序,那么可覆蓋此方法〔2〕findLoadedClass此方法擔任從當前ClassLoader實例對象的緩存中尋覓已加載的類,調用的為native的方法?!?〕findClass此方法直接拋出ClassNotFoundException,因此需求經過覆蓋loadClass或此方法來以自定義的方式加載相應的類。(4)findSystemClass此方法擔任從SystemClassLoader中尋覓類,如未找到,那么繼續從BootstrapClassLoader中尋覓,如依然為找到,那么前往null。(5)defineClass此方法擔任將二進制的字節碼轉換為Class對象(6)resolveClass此方法擔任完成Class對象的鏈接,如已鏈接過,那么會直接前往。

JVM的體系構造之類加載器四、簡單的classLoader例子/**重寫ClassLoader類的findClass方法,將一個字節數組轉換為Class類的實例*/publicClass<?>findClass(Stringname)throwsClassNotFoundException{byte[]b=null;try{b=loadClassData(AutoClassLoader.FormatClassName(name));}catch(Exceptione){e.printStackTrace();}returndefineClass(name,b,0,b.length);}/**將指定途徑的.class文件轉換成字節數組*/privatebyte[]loadClassData(Stringfilepath)throwsException{intn=0;BufferedInputStreambr=newBufferedInputStream(newFileInputStream(newFile(filepath)));ByteArrayOutputStreambos=newByteArrayOutputStream();while((n=br.read())!=-1){bos.write(n);}br.close();returnbos.toByteArray();}JVM的體系構造之類加載器四、簡單的classLoader例子/**格式化文件所對應的途徑*/publicstaticStringFormatClassName(Stringname){

FILEPATH=DEAFAULTDIR+name+".class";returnFILEPATH;}

/**main方法測試*/publicstaticvoidmain(String[]args)throwsException{

AutoClassLoaderacl=newAutoClassLoader();Classc=acl.findClass("testClass");Objectobj=c.newInstance();Methodm=c.getMethod("getName",newClass[]{String.class,int.class});m.invoke(obj,"他好",123);System.out.println(c.getName());System.out.println(c.getClassLoader());System.out.println(c.getClassLoader().getParent());}內容JVM的生命周期JVM的體系構造JVM類加載器JVM執行引擎JVM運轉時數據區JVM渣滓回收問題JVM的體系構造之執行引擎一、JVM經過執行引擎來完成字節碼的執行,在執行過程中JVM采用的是本人的一套指令系統,每個線程在創建后,都會產生一個程序計數器〔pc〕和?!睸tack〕,其中程序計數器中存放了下一條將要執行的指令,Stack中存放StackFrame,表示的為當前正在執行的方法,每個方法的執行都會產生StackFrame,StackFrame中存放了傳送給方法的參數、方法內的部分變量以及操作數棧,操作數棧用于存放指令運算的中間結果,指令擔任從操作數棧中彈出參與運算的操作數,指令執行終了后再將計算結果壓回到操作數棧,當方法執行終了后那么從Stack中彈出,繼續其他方法的執行。在執行方法時JVM提供了invokestatic、invokevirtual、invokeinterface和invokespecial四種指令來執行〔1〕invokestatic:調用類的static方法〔2〕invokevirtual:調用對象實例的方法〔3〕invokeinterface:將屬性定義為接口來進展調用〔4〕invokespecial:JVM對于初始化對象〔Java構造器的方法為:<init>〕以及調用對象實例中的私有方法時。

JVM的體系構造之執行引擎二、反射機制是Java的亮點之一,基于反射可動態調用某對象實例中對應的方法、訪問查看對象的屬性等,而無需在編寫代碼時就確定需求創建的對象,這使得Java可以實現很靈敏的實現對象的調用,代碼例如如下:ClassactionClass=Class.forName(外部實現類);Methodmethod=actionClass.getMethod(“execute〞,null);Objectaction=actionClass.newInstance();method.invoke(action,null);反射的關鍵:要實現動態的調用,最明顯的方法就是動態的生成字節碼,加載到JVM中并執行

JVM的體系構造之執行引擎〔1〕ClassactionClass=Class.forName(外部實現類);調用本地方法,運用調用者所在的ClassLoader來加載創建出Class對象;〔2〕Methodmethod=actionClass.getMethod(“execute〞,null);校驗此Class能否為public類型的,以確定類的執行權限,如不是public類型的,那么直接拋出SecurityException;調用privateGetDeclaredMethods來獲取到此Class中一切的方法,在privateGetDeclaredMethods對此Class中一切的方法的集合做了緩存,在第一次時會調用本地方法去獲??;掃描方法集合列表中能否有一樣方法名以及參數類型的方法,如有那么復制生成一個新的Method對象前往;如沒有那么繼續掃描父類、父接口中能否有此方法,如依然沒找到方法那么拋出NoSuchMethodException;

JVM的體系構造之執行引擎〔3〕Objectaction=actionClass.newInstance();第一步:校驗此Class能否為public類型,如權限缺乏那么直接拋出SecurityException;第二步:如沒有緩存的構造器對象,那么調用本地方法獲取到構造器,并復制生成一個新的構造器對象,放入緩存,如沒有空構造器那么拋出InstantiationException;第三步:校驗構造器對象的權限;第四步:執行構造器對象的newInstance方法;構造器對象的newInstance方法判別能否有緩存的ConstructorAccessor對象,假設沒有那么調用sun.reflect.ReflectionFactory生成新的ConstructorAccessor對象;第五步:sun.reflect.ReflectionFactory判別能否需求調用本地代碼,可經過sun.reflect.noInflation=true來設置為不調用本地代碼,在不調用本地代碼的情況下,就轉交給MethodAccessorGenerator來處置了;第六步:MethodAccessorGenerator中的generate方法根據JavaClass格式規范生成字節碼,字節碼中包括了ConstructorAccessor對象需求的newInstance方法,此newInstance方法對應的指令為invokespecial,所需的參數那么從外部壓入,生成的Constructor類的名字以:sun/reflect/GeneratedSerializationConstructorAccessor或sun/reflect/GeneratedConstructorAccessor開頭,后面跟隨一個累計創建的對象的次數;第七步:在生成了字節碼后將其加載到當前的ClassLoader中,并實例化,完成ConstructorAccessor對象的創建過程,并將此對象放入構造器對象的緩存中;最后一步:執行獲取的constructorAccessor.newInstance,這步和規范的方法調用沒有任何區別。

JVM的體系構造之執行引擎〔4〕method.invoke(action,null);這步執行的過程和上一步根本類似,只是在生成字節碼時生成的方法改為了invoke,其調用的目的改為了傳入的對象的方法,同時生成的類名改為了:sun/reflect/GeneratedMethodAccessor。注:但是getMethod是非常耗性能的,一方面是權限的校驗,另外一方面一切方法的掃描以及Method對象的復制,因此在運用反射調用多的系統中應緩存getMethod前往的Method對象

JVM的體系構造之執行引擎2、執行技術主要的執行技術有:解釋,即時編譯,自順應優化、芯片級直接執行〔1〕解釋屬于第一代JVM,〔2〕即時編譯JIT屬于第二代JVM,〔3〕自順應優化〔目前Sun的HotspotJVM采用這種技術〕那么汲取第一代JVM和第二代JVM的閱歷,采用兩者結合的方式

〔4〕自順應優化:開場對一切的代碼都采取解釋執行的方式,并監視代碼執行情況,然后對那些經常調用的方法啟動一個后臺線程,將其編譯為本地代碼,并進展仔細優化。假設方法不再頻繁運用,那么取消編譯過的代碼,仍對其進展解釋執行。

內容JVM的生命周期JVM的體系構造JVM類加載器JVM執行引擎JVM運轉時數據區JVM渣滓回收問題JVM的體系構造之運轉時數據區一、JVM在運轉時將數據劃分為了6個區域來存儲,而不僅僅是大家熟知的Heap區域,這6個區域圖示如下:

JVM的體系構造之運轉時數據區第一塊:PC存放器PC存放器是用于存儲每個線程下一步將執行的JVM指令,如該方法為native的,那么PC存放器中不存儲任何信息。第二塊:JVM棧JVM棧是線程私有的,每個線程創建的同時都會創建JVM棧,JVM棧中存放的為當前線程中部分根本類型的變量〔java中定義的八種根本類型:boolean、char、byte、short、int、long、float、double〕、部分的前往結果以及StackFrame,非根本類型的對象在JVM棧上僅存放一個指向堆上的地址第三塊:堆〔Heap〕Heap是大家最為熟習的區域,它是JVM用來存儲對象實例以及數組值的區域,可以以為Java中一切經過new創建的對象的內存都在此分配,Heap中的對象的內存需求等待GC進展回收。

JVM的體系構造之運轉時數據區JVM將Heap分為NewGeneration和OldGeneration〔或TenuredGeneration〕兩塊來進展管理:〔1〕NewGeneration又稱為新生代,程序中新建的對象都將分配到新生代中,新生代又由EdenSpace和兩塊SurvivorSpace構成,可經過-Xmn參數來指定其大小〔2〕OldGeneration又稱為舊生代,用于存放程序中經過幾次渣滓回收還存活的對象,例如緩存的對象等,舊生代所占用的內存大小即為-Xmx指定的大小減去-Xmn指定的大小。

JVM的體系構造之運轉時數據區對堆的解釋:〔1〕堆是JVM中一切線程共享的,因此在其上進展對象內存的分配均需求進展加鎖,這也導致了new對象的開銷是比較大的〔2〕鑒于上面的緣由,SunHotspotJVM為了提升對象內存分配的效率,對于所創建的線程都會分配一塊獨立的空間,這塊空間又稱為TLAB〔ThreadLocalAllocationBuffer〕,其大小由JVM根據運轉的情況計算而得,在TLAB上分配對象時不需求加鎖,因此JVM在給線程的對象分配內存時會盡量的在TLAB上分配,在這種情況下JVM中分配對象內存的性能和C根本是一樣高效的,但假設對象過大的話那么依然是直接運用堆空間分配〔3〕TLAB僅作用于新生代的EdenSpace,因此在編寫Java程序時,通常多個小的對象比大的對象分配起來更加高效,但這種方法同時也帶來了兩個問題,一是空間的浪費,二是對象內存的回收上依然沒法做到像Stack那么高效,同時也會添加回收時的資源的耗費,可經過在啟動參數上添加-XX:+PrintTLAB來查看TLAB這塊的運用情況。

JVM的體系構造之運轉時數據區第四塊:方法區域〔MethodArea〕〔1〕方法區域存放了所加載的類的信息〔稱號、修飾符等〕、類中的靜態變量、類中定義為final類型的常量、類中的Field信息、類中的方法信息,當開發人員在程序中經過Class對象中的getName、isInterface等方法來獲取信息時,這些數據都來源于方法區域,可見方法區域的重要性,同樣,方法區域也是全局共享的,在一定的條件下它也會被GC,當方法區域需求運用的內存超越其允許的大小時,會拋出OutOfMemory的錯誤信息?!?〕在SunJDK中這塊區域對應的為PermanetGeneration,又稱為耐久代,默以為64M,可經過-XX:PermSize以及-XX:MaxPermSize來指定其大小。第五塊:運轉時常量池〔RuntimeConstantPool〕類似C中的符號表,存放的為類中的固定的常量信息、方法和Field的援用信息等,其空間從方法區域中分配。第六塊:本地方法堆?!睳ativeMethodStacks〕JVM采用本地方法堆棧來支持native方法的執行,此區域用于存儲每個native方法調用的形狀。

內容JVM的生命周期JVM的體系構造JVM類加載器JVM執行引擎JVM運轉時數據區JVM渣滓回收問題JVM的體系構造之內存回收一、JVM中自動的對象內存回收機制稱為:GC〔GarbageCollection〕1、GC的根本原理:為將內存中不再被運用的對象進展回收,GC中用于回收內存中不被運用的對象的方法稱為搜集器,由于GC需求耗費一些資源和時間的,Java在對對象的生命周期特征進展分析后,在V1.2以上的版本采用了分代的方式來進展對象的搜集,即按照新生代、舊生代的方式來對對象進展搜集,以盡能夠的縮短GC對運用呵斥的暫停〔1〕對新生代的對象的搜集稱為minorGC,〔2〕對舊生代的對象的搜集稱為FullGC,〔3〕程序中自動調用System.gc()強迫執行的GC為FullGC,

JVM的體系構造之內存回收二、JVM中自動內存回收機制〔1〕援用計數搜集器原理:援用計數是標識Heap中對象形狀最明顯的一種方法,援用計數的方法簡單來說就是對每一個

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
  • 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論