JVM運行機制理解整理

一.概述

網絡上有一些有關JVM運行機制的文章和視頻講解的已經很詳細了。本文主要是對零散的知識加上自己的理解進行梳理一下。

二.JVM運行機制

1.JVM啓動流程

2.JVM內部結構

當JVM使用類裝載器裝載某個類時,它首先要定位對應的class文件,然後讀入這個class文件,最後,JVM提取該文件的內容信息,並將這些信息存儲到方法區,最後返回一個class實例。


(一).方法區

(1).什麼是方法區?

方法區是系統分配的一個內存邏輯區域,是用來存儲類型信息的。

(2).方法區的主要特點?

A.方法區是線程安全的。由於所有的線程都共享方法區,所以,方法區裏的數據訪問必須被設計成線程安全的。例如,假如同時有兩個線程都企圖訪問方法區中的同一個類,而這個類還沒有被裝入JVM,那麼只允許一個線程去裝載它,而其它線程必須等待。

B.方法區的大小不必是固定的,JVM可根據應用需要動態調整。同時,方法區也不一定是連續的,方法區可以在一個堆(甚至是JVM自己的堆)中自由分配。

C.方法區也可被垃圾收集,當某個類不在被使用(不可觸及)時,JVM將卸載這個類,進行垃圾收集。

(3).方法區裏存的都是類型信息,也就是類的信息,而類的信息又包括以下內容:

A.類的全限定名、類的全路徑名、類的直接超類的全限定名(如果這個類是Object,則它沒有超類)。

B.這個類是類型類還是接口類。

C.訪問修飾符,如public、abstract、final等。

D.所有的直接接口全限定名的有序列表(假如它實現了多個接口) 。

E.常量池、字段、方法信息、類變量信息(靜態變量) 。

F.裝載該類的裝載器的引用(classLoader)、類型引用(class) 。

G.不過JDK6的時候,String等常量信息存在方法區中,JDK7的時候就移動到了堆中。

(二).虛擬機棧

(1).什麼是java虛擬機棧?

描述的是Java方法執行的內存模型,每個方法在執行的同時都會創建一個棧幀用於存儲局部變量表、操作數棧、動態鏈接、方法出口等信息。每一個方法從調用直至執行完成的過程,就對應着一個棧幀在虛擬機中入棧道出棧的過程。

(2).java虛擬機棧的主要特點?

A.線程私有。

B.後進先出(LIFO)棧。

C.存儲棧幀,支撐java方法的調用、執行和退出。

D.可能出現OutOfMemoryError異常和StackOverflowError異常。

(三)本地方法棧

(1).什麼是本地方法棧?

本地方法棧與虛擬機棧所發揮的作用是非常相似的,它們之間的區別不過是java虛擬機棧是爲了執行java方法(也就是字節碼)服務的,本地方法棧是java虛擬機爲了Native方法所服務的。在虛擬機規範中對本地方法棧中方法使用的語言、使用方式與數據結構並沒有強制規定,因此具體的虛擬機可以自由實現它。甚至有的虛擬機(如Sun HotSpot虛擬機)直接就把本地方法棧和虛擬機棧合二爲一。

(2).本地方法棧的主要特點?

A.線程私有。

B.後進先出(LIFO)棧。

C.作用是支撐Native方法的調用、執行和退出。

D.可能出現OutOfMemoryError異常和StackOverflowError異常。

(3).棧幀的概念和特徵

A.Java虛擬機棧中存儲的內容,它被用於儲存數據和部分過程結果的數據結構,同時也被用來處理動態鏈接、方法返回值和異常分派。

B.一個完整的棧幀包含:局部變量表、操作數棧、動態連接信息、方法正常完成和異常完成信息。

(四).堆

(1).什麼是堆?

Java中的堆是JVM所管理的最大的一塊內存空間,是一個運行時數據區,通過new等指令創建,不需要程序代碼顯式釋放。主要用於存放各種類的實例對象。在Java中,堆被劃分成兩個不同的區域:一塊是新生代(New Generation), 另一塊是老年代(Old Generation)。在New Generation中,又被劃分爲三個區域:Eden、From Survivor、To Survivor。Eden的空間,主要是用來存放新生的對象,From Survivor Spaces、To Survivor Spaces, 它們用來存放每次垃圾回收後存活下來的對象。

在Old Generation中,主要存放應用程序中生命週期長的內存對象,還有個Permanent Generation,主要用來放JVM自己的反射對象,比如類對象和方法對象等。

在New Generation塊中,垃圾回收一般用複製算法,速度快。每次GC的時候,存活下來的對象首先由Eden拷貝到某個Survivor Space, 當Survivor Space空間滿了後, 剩下的live對象就被直接拷貝到Old Generation中去。因此,每次GC後,Eden內存塊會被清空在Old Generation塊中,垃圾回收一般用標記整理的算法,速度慢些,但減少內存要求。

(2).堆的主要特點?

堆的優勢是可以動態地分配內存大小,生存期也不必事先告訴編譯器,Java的垃圾收集器會自動收走這些不再使用的數據。缺點是由於要在運行時動態分配內存,存取速度較慢。

(五).程序計數器

(1).什麼是程序計數器?

《深入理解Java虛擬機》中是這樣解釋的:程序計數器(Program Counter Register)是一塊較小的內存空間,它的作用可以看做是當前線程所執行的字節碼的行號指示器。在虛擬機的概念模型裏(僅是概念模型,各種虛擬機可能會通過一些更高效的方式去實現),字節碼解釋器工作時就是通過改變這個計數器的值來選取下一條需要執行的字節碼指令,分支、循環、跳轉、異常處理、線程恢復等基礎功能都需要依賴這個計數器來完成。

由於Java虛擬機的多線程是通過線程輪流切換並分配處理器執行時間的方式來實現的,在任何一個確定的時刻,一個處理器(對於多核處理器來說是一個內核)只會執行一條線程中的指令。因此,爲了線程切換後能恢復到正確的執行位置,每條線程都需要有一個獨立的程序計數器,各條線程之間的計數器互不影響,獨立存儲,我們稱這類內存區域爲“線程私有”的內存。

如果線程正在執行的是一個Java方法,這個計數器記錄的是正在執行的虛擬機字節碼指令的地址;如果正在執行的是Natvie方法,這個計數器值則爲空(Undefined)。此內存區域是唯一一個在Java虛擬機規範中沒有規定任何OutOfMemoryError情況的區域。

發佈了46 篇原創文章 · 獲贊 40 · 訪問量 27萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章