jvm全稱是Java Virtual Machine(java虛擬機)
它之所以被稱之為是
虛擬
的
就是因為它僅僅是由一個規范來定義的抽象計算機
我們平時經常使用的Sun HotSpot虛擬機只是其中一個具體的實現(另外還有BEA JRockit
IBM J
等等虛擬機)
在實際的計算機上通過軟件來實現一個虛擬計算機
與VMWare等類似軟件不同
你是看不到jvm的
它存在於內存
當啟動一個Java程序時
一個虛擬機實例也就誕生了
當該程序關閉退出
這個虛擬機實例也就隨之消亡
如果在同一台計算機上同時運行三個Java程序
將得到三個Java虛擬機實例
每個Java程序都運行於它自己的Java虛擬機實例中
Java虛擬機在執行Java程序的過程中會把它所管理的內存劃分為若干個不同的數據區域
根據《Java虛擬機規范(第
版)》的規定
Java虛擬機所管理的內存將會包括以下幾個運行時數據區域
如下圖
所示
圖
Java虛擬機的內部體系結構
下面先對圖中各部分做個簡單的說明
class文件
虛擬機並不關心Class的來源是什麼語言
只要它符合Java class文件格式就可以在Java虛擬機中運行
使用Java編譯器可以把Java代碼編譯為存儲字節碼的Class文件
使用JRuby等其他語言的編譯器一樣可以把程序代碼編譯成Class文件
類裝載器子系統
負責查找並裝載Class 文件到內存
最終形成可以被虛擬機直接使用的Java類型
方法區
在類裝載器加載class文件到內存的過程中
虛擬機會提取其中的類型信息
並將這些信息存儲到方法區
方法區用於存儲已被虛擬機加載的類信息
常量
靜態變量
即時編譯器編譯後的代碼等數據
由於所有線程都共享方法區
因此它們對方法區數據的訪問必須被設計為是線程安全的
堆
存儲Java程序創建的類實例
所有線程共享
因此設計程序時也要考慮到多線程訪問對象(堆數據)的同步問題
Java棧
Java棧是線程私有的
每當啟動一個新線程時
Java虛擬機都會為它分配一個Java棧
Java棧以幀為單位保存線程的運行狀態
虛擬機只會直接對Java棧執行兩種操作
以幀為單位的壓棧或出棧
當線程調用java方法時
虛擬機壓入一個新的棧幀到該線程的java棧中
當方法返回時
這個棧幀被從java棧中彈出並拋棄
一個棧幀包含一個java方法的調用狀態
它存儲有局部變量表
操作棧
動態鏈接
方法出口等信息
程序計數器
一個運行中的Java程序
每當啟動一個新線程時
都會為這個新線程創建一個自己的PC(程序計數器)寄存器
程序計數器的作用可以看做是當前線程所執行的字節碼的行號指示器
字節碼解釋器工作時就是通過改變這個計數器的值來選取下一條需要執行的字節碼指令
分支
循環
跳轉
異常處理
線程恢復等基礎功能都需要依賴這個計數器來完成
如果線程正在執行的是一個Java方法
這個計數器記錄的是正在執行的虛擬機字節碼指令的地址
如果正在執行的是Natvie方法
這個計數器值則為空(Undefined)
本地方法棧
本地方法棧與虛擬機棧所發揮的作用是非常相似的
其區別不過是虛擬機棧為虛擬機執行Java方法(也就是字節碼)服務
而本地方法棧則是為虛擬機使用到的Native方法服務
任何本地方法接口都會使用某種本地方法棧
當線程調用Java方法時
虛擬機會創建一個新的棧幀並壓入Java棧
然而當它調用的是本地方法時
虛擬機會保持Java棧不變
不再在線程的Java棧中壓入新的幀
虛擬機只是簡單地動態鏈接並直接調用指定的本地方法
如果某個虛擬機實現的本地方法接口是使用C連接模型的話
那麼它的本地方法棧就是C棧
執行引擎
負責執行字節碼
方法的字節碼是由Java虛擬機的指令序列構成的
每一條指令包含一個單字節的操作碼
後面跟隨
個或多個操作數
執行引擎執行字節碼時
首先取得一個操作碼
如果操作碼有操作數
取得它的操作數
它執行操作碼和跟隨的操作數規定的動作
然後再取得下一個操作碼
這個執行字節碼的過程在線程完成前將一直持續
From:http://tw.wingwit.com/Article/program/Java/hx/201311/25838.html