亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

深入淺析Java中 JVM的原理

發布時間:2020-11-17 15:16:18 來源:億速云 閱讀:156 作者:Leah 欄目:編程語言

這篇文章將為大家詳細講解有關深入淺析Java中 JVM的原理,文章內容質量較高,因此小編分享給大家做個參考,希望大家閱讀完這篇文章后對相關知識有一定的了解。

JVM是一種用于計算設備的規范,它是一個虛構出來的計算機,是通過在實際的計算機上仿真模擬各種計算機功能來實現的。Java虛擬機包括一套字節碼指令集、一組寄存器、一個棧、一個垃圾回收堆和一個存儲方法域。 JVM屏蔽了與具體操作系統平臺相關的信息,使Java程序只需生成在Java虛擬機上運行的目標代碼(字節碼),就可以在多種平臺上不加修改地運行。是運行Java應用最底層部分。

JDK(Java Development kit)

整個Java的核心,包括了Java運行環境(Java Runtime Envirnment),一堆Java工具(編譯,debug等)和Java基礎的類庫(rt.jar)。是開發java應用的基礎。

JRE(Java Runtime Environment,Java運行環境)

運行JAVA程序所必須的環境的集合,包含JVM標準實現及Java核心類庫。運行java應用的基礎。

J2SE(Java 2 Platform,Standard Edition)。

包含那些構成Java語言核心的類。比如:數據庫連接、接口定義、輸入/輸出、網絡編程

J2EE(Java 2 Platform,Enterprise Edition)。

Enterprise Edition(企業版) J2EE 包含J2SE 中的類,并且還包含用于開發企業級應用的類。比如:EJB、servlet、JSP、XML、事務控制。

主要JVM

首先,JVM是一套規范。很多公司均實現了各自的虛擬機。常見的有

HotSpot JVM(sun)
Jrockit JVM(BEA公司的JVM,應用于weblogic)
IBM JVM
Apache Harmony

其中,我們常用的是HotSpot JVM.

JVM結構

深入淺析Java中 JVM的原理

第一步(編譯):

創建完源文件之后,程序會先被編譯為.class文件。Java編譯一個類時,如果這個類所依賴的類還沒有被編譯,編譯器就會先編譯這個被依賴的類,然后 引用,這個有點象make。如果java編譯器在指定目錄下找不到該類所其依賴的類的.class文件或者.java源文件的話,編譯器話 報“cant find symbol”的錯誤。

第二步(運行):

Java類運行的過程大概可分為兩個過程:1、類的加載  2、類的執行。

需要說明的是:JVM主要在程序第一次主動使用類的時候,才會去加載該類。也就是說,JVM并不是在一開始就把一個程序就所有的類都加載到內存中,而是到不得不用的時候才把它加載進來,而且只加載一次。

1、 在 編譯好java程序得到MainApp.class文件后,在命令行上敲java AppMain。系統就會啟動一個jvm進程,jvm進程從classpath路徑中找到一個名為AppMain.class的二進制文件,將 MainApp的類信息加載到運行時數據區的方法區內,這個過程叫做MainApp類的加載。

2、 (java命令)然后JVM找到AppMain的主函數入口,開始執行main函數

3、 (類加載器)執行過程中,會創建對象。JVM會首先從方法區加載類信息和相關常量,class加載完畢之后,在堆上為對象分配內存,然后調用初始化實例,當然這時候實例保持指向class類型信息,這個信息保存在方法區中。

4、 (執行引擎)調用實例方法時,會根據引用找到對象信息,進而可定位對應的class類型信息,和方法表。

5、 (執行引擎)執行方法時,在虛擬機棧中進行,分配棧幀,隨著入棧出棧,完成方法調用操作。

執行引擎

運行Java的每一個線程都是一個獨立的虛擬機執行引擎的實例。從線程生命周期的開始到結束,他要么在執行字節碼,要么在執行本地方法。一個線程可能通過解釋或者使用芯片級指令直接執行字節碼,或者間接通過JIT執行編譯過的本地代碼。我們上文講到的main函數,也就是執行引擎的操作入口。

Class文件

實際上,Class文件中方法的字節碼流就是有JVM的指令序列構成的。每一條指令包含一個單字節的操作碼,后面跟隨0個或多個操作數。

iload_0    // 把存儲在局部變量區中索引為0的整數壓入操作數棧。
iload_1    // 把存儲在局部變量區中索引為1的整數壓入操作數棧。
iadd         // 從操作數棧中彈出兩個整數相加,在將結果壓入操作數棧。
istore_2   // 從操作數棧中彈出結果

JVM運行時數據區

1)程序計數器(線程私有)

當前線程所執行的字節碼的行號指示器,通過改變這個計數器的值,確定下一條要執行的命令。分支,循環,跳轉都需要它的支持。

它是線程私有的,每個線程都有專屬于自己的程序記數器,線程之間互不影響,獨立存儲,保證了線程切換后,可以恢復到原先執行位置。

2)Java虛擬機棧(線程私有)

每個方法的執行,同時都會在虛擬機棧上創建一個棧幀。用于存儲局部變量表,操作數棧,方法出口,動態鏈接等。一個方法的執行周期,同時也就對應著棧幀的出棧入棧操作。有時候方法的遞歸,會造成大量的棧幀,達到一定的深度,會報StackOverflowError異常。有一點需要說明:在編譯器編譯Java代碼時,就已經在字節碼中為每個方法都設置好了局部變量區和操作數棧的數據和大小。并在JVM首次加載方法所屬的Class文件時, 就將這些數據放進了方法區。因此在線程調用方法時,只需要根據方法區中的局部變量區和操作數棧的大小來分配一個新的棧幀的內存大小,并堆入Java棧。

局部變量區: 用來存放方法中的所有局部變量值,包括傳遞的參數。這些數據會被組織成以一個字長(32bit或64bit)為單位的數組結構(以索引0開始)中。其中類 型為int, float, reference(引用類型,記錄對象在堆中地址)和returnAddress(一種JVM內部使用的基本類型)的值占用1個字長,而byte, char和shot會擴大成1個字長存儲,long,double則使用2個字長。

 操作數棧: 用來在執行指令的時候存儲和使用中間結果數據。

幀數據區: 常量池的解析,正常方法返回以及異常派發機制的信息數據都存儲在其中。

3)本地方法棧(線程私有)

與Java虛擬機棧類似,只不過該區域是為native方法提供服務。

4)方法區(Perm)(線程共享)

    存儲已被虛擬機加載的類信息,常量,靜態變量,即時編譯后的代碼等數據。包含運行時常量池,用于存放編譯器生成的各種字面量和符號引用,這部分內容是在類加載后進入方法區運行時常量池中。

5)堆

深入淺析Java中 JVM的原理

堆是整個內存數據區最負責的部分,負責對象的創建。同時,垃圾回收的主要工作也在于此。堆又進一步進行細分,主要是為了滿足垃圾回收。

堆的組成

Eden(伊甸園):對象創建的入口。

Survivor Space:用于保存在eden space內存池中經過垃圾回收后沒有被回收的對象,也就是“幸存還活著”的對象。

幸存者0區(Survivor 0 space)和幸存者1區(Survivor1 space):當伊甸園的空間用完時,程序又需要創建對象;此時JVM的垃圾回收器將對伊甸園區進行垃圾回收,將伊甸園區中的不再被其他對象所引用的對象 進行銷毀工作。同時將伊甸園中的還有其他對象引用的對象移動到幸存者0區。幸存者0區就是用于存放伊甸園垃圾回收時所幸存下來的JAVA對象。

當將伊甸園中的還有其他對象引用的對象移動到幸存者0區時,如果幸存者0區也沒有空間來存放這些對象時,JVM的垃圾回收器將對幸存者0區進行垃圾 回收處理,將幸存者0區中不在有其他對象引用的JAVA對象進行銷毀,將幸存者0區中還有其他對象引用的對象移動到幸存者1區。幸存者1區的作用就是用于 存放幸存者0區垃圾回收處理所幸存下來的JAVA對象。

Tenured :對象經過survivor 1 space內存池,每經歷過一次垃圾回收,年齡就增加1,超過設定閥值后,被移入終身代,當然也包括由于擔保機制移入的對象。對于新生代和老年代,垃圾回收器對其態度不同。發生在新生代的回收頻率頻繁,大部分對象是“朝生夕死”,收集算法一般采用高效簡單的復制算法,也就是上文描述的對象轉移操作(Eden->survivor 0,survivor 0->survivor 1)。發生在該區域的垃圾回收為Young GC.對于老年代,由于大部分對象主要為存活率高的對象,垃圾回收器采用”標記-整理“算法。發生在該區域的垃圾回收為FULL GC.

堆相關參數

(影響堆空間劃分,進而會影響GC發生頻率)JVM調優工作,主要是基于這些參數,進行適當調整管理,達到調整堆內存大小及比例大小,以滿足實際業務需求。另外還包括方法區。

-Xms:設置 Java 應用程序啟動時的初始堆大小;
-Xmx:設置 Java 應用程序能獲得的最大堆大小;
-Xss:設置線程棧的大小;
-XX:MinHeapFreeRatio:設置堆空間最小空閑比例。當堆空間的空閑內存小于這個數值時,JVM 便會擴展堆空間;
-XX:MaxHeapFreeRatio:設置堆空間的最大空閑比例。當堆空間的空閑內存大于這個數值時,便會壓縮堆空間,得到一個較小的堆;
-XX:NewSize:設置新生代的大小;
-XX:NewRatio:設置老年代與新生代的比例,它等于老年代大小除以新生代大小;
-XX:SurvivorRatio:新生代中 eden 區與 survivor 區的比例;
-XX:MaxPermSize:設置最大的持久區大小;
-XX:TargetSurvivorRatio: 設置 survivor 區的可使用率。當 survivor 區的空間使用率達到這個數值時,會將對象送入老年代。

對象的生命周期

  創建階段

1、檢查指令的參數,是否能在常量池中定位到一個類的符號引用,如果是引用,判斷代表的類是否加載,解析和初始化過

2、如果沒有加載,則必須進行加載,解析和初始化

3、類加載檢查,這時候已經知道所需內存的大小。

4、分配內存。從java堆中劃分一塊大小確定的內存。支持2種方式,至于選擇哪種方式分配內存,與java堆是否規整有關(也就是是否空間空間和使用空間相互交錯情況)。1.指針碰撞(分界點的指示器移動);2.空閑列表方式。然而,java堆是否規整,則取決于垃圾收集器的工作方式。此外,在分配內存時還要考慮多線程情況,保證原子性。分配內存的原子性有2種方式進行保證(CAS 和 本地線程分配緩沖-XX +/- UseTLAB)。

5)、分配內存完成后,初始化內存空間(初始化為0)

6、維護對象的對象頭信息。如元數據信息,哈希碼,GC分代年齡,鎖信息,類元指針。

7、調用init方法,按照程序員意愿進行初始化。

     <7.1> 從超類到子類對static成員進行初始化;
     <7.2> 超類成員變量按順序初始化,遞歸調用超類的構造方法;
      <7.3> 子類成員變量按順序初始化,子類構造方法調用。

應用階段

分為強引用、軟引用、虛引用、若引用

   不可視階段;

當一個對象處于不可視階段,說明我們在其他區域的代碼中已經不可以在引用它,其強引用已經消失,例如,本地變量超出了其可視的范圍。

   不可到達階段;

處于JVM對象生命周期不可到達階段的對象,在虛擬機所管理的對象引用根集合中再也找不到直接或間接的強引用,這些對象通常是指所有線程棧中的臨時變量, 所有已裝載的類的靜態變量或者對本地代碼接口(JNI)的引用。這些對象都是要被垃圾回收器回收的預備對象,但此時該對象并不能被垃圾回收器直接回收。其 實所有垃圾回收算法所面臨的問題是相同的——找出由分配器分配的,但是用戶程序不可到達的內存塊。

   可收集階段、終結階段、釋放階段 ;

當一個對象處于可收集階段、終結階段與釋放階段時

<1> 回收器發現該對象已經不可達。 

     <2> finalize方法已經被執行。 

     <3> 對象空間已被重用。

關于深入淺析Java中 JVM的原理就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

耿马| 滁州市| 闵行区| 吉林市| 铁岭县| 灵石县| 印江| 凤冈县| 上思县| 慈溪市| 嘉善县| 宁安市| 大英县| 保定市| 万盛区| 贡山| 铜山县| 象州县| 油尖旺区| 万州区| 澄城县| 体育| 衡水市| 赣榆县| 泰和县| 凤阳县| 灵宝市| 谷城县| 岳阳县| 尚志市| 昌图县| 鄯善县| 温泉县| 新安县| 瓦房店市| 饶阳县| 仁怀市| 明溪县| 寿阳县| 蓬溪县| 宁城县|