JVM 学习笔记 1. JVM 运行模型
目錄
1. JVM 啟動(dòng)流程
如下圖所示:
2. JVM 基本結(jié)構(gòu)
兩幅經(jīng)典的模型圖:
其中:
棧的執(zhí)行過程
JVM 沒有寄存器(除PC),所有的參數(shù)傳遞都使用操作數(shù)棧。
public static int add(int a,int b){int c = 0;c = a + b;return c; }編譯之后,注意操作數(shù)棧如何實(shí)現(xiàn)參數(shù)傳遞。
0: iconst_0 // 0壓棧1: istore_2 // 彈出int,存放于局部變量22: iload_0 // 把局部變量0壓棧3: iload_1 // 局部變量1壓棧4: iadd // 彈出2個(gè)變量,求和,結(jié)果壓棧5: istore_2 // 彈出結(jié)果,放于局部變量26: iload_2 // 局部變量2壓棧7: ireturn // 返回局部變量表和操作數(shù)棧的變化過程:
棧上分配
public class OnStackTest {public static void alloc() {byte[] b = new byte[2];b[0] = 1;}public static void main(String[] args) {long b = System.currentTimeMillis();for (int i = 0; i < 100000000; i++) {alloc();}long e = System.currentTimeMillis();System.out.println(e - b);} }默認(rèn)運(yùn)行,采用了棧上分配了. 測(cè)試結(jié)果:
? jvm-learning java com.nil2inf.memory.OnStackTest 52 ? jvm-learning java -server -Xmx10m -Xms10m -XX:+DoEscapeAnalysis -XX:+PrintGC com.nil2inf.memory.OnStackTest 40 ? jvm-learning java -server -Xmx10m -Xms10m -XX:-DoEscapeAnalysis -XX:+PrintGC com.nil2inf.memory.OnStackTest [GC 2624K->432K(9856K), 0.0014784 secs] [GC 3056K->416K(9856K), 0.0006314 secs] [GC 3040K->432K(9856K), 0.0004287 secs] [GC 3056K->416K(9728K), 0.0003950 secs] ... ... [GC 3280K->400K(9984K), 0.0001506 secs] [GC 3280K->400K(10048K), 0.0001993 secs] [GC 3408K->400K(10048K), 0.0001092 secs] ... ... [GC 3664K->400K(10176K), 0.0001128 secs] 582棧上分配:
- 棧上分配、標(biāo)量替換技術(shù)是JVM的一項(xiàng)優(yōu)化技術(shù),涉及到逃逸分析和標(biāo)量替換。
- 通常只有沒有逃逸的小對(duì)象,才可以棧上分配。反之,大對(duì)象或者逃逸對(duì)象無(wú)法棧上分配。
- 棧上分配的目的是減清 GC 的壓力。
3. 內(nèi)存模型
read and load 從主存復(fù)制變量到當(dāng)前工作內(nèi)存
use and assign 執(zhí)行代碼,改變共享變量值
store and write 用工作內(nèi)存數(shù)據(jù)刷新主存相關(guān)內(nèi)容
可見性
一個(gè)線程修改了變量,其他線程可以立即知道。
如何確保可見性:
- volatile
- synchronized (unlock之前,寫變量值回主存)
- final(一旦初始化完成,其他線程就可見)
有序性
在本線程內(nèi),操作都是有序的。在線程外觀察,操作都是無(wú)序的。(指令重排 或 主內(nèi)存同步延時(shí))。
重排序
指令重排序。
4. 虛擬機(jī)的運(yùn)行方式
虛擬機(jī)中存在兩種運(yùn)行方式:分為解釋和編譯。
字節(jié)碼指令編譯為本機(jī)機(jī)器指令過程,有解釋器或者編譯器完成.
a. 解釋
解釋是最簡(jiǎn)單的字節(jié)碼編譯形式. 解釋器查找每條字節(jié)碼指令對(duì)應(yīng)的硬件編碼,再由 CPU 執(zhí)行相應(yīng)的硬件指令。
這個(gè)過程可以準(zhǔn)確執(zhí)行字節(jié)碼,沒有機(jī)會(huì)對(duì)某個(gè)指令集合進(jìn)行優(yōu)化,難以發(fā)揮目標(biāo)平臺(tái)處理器的最佳性能。
b. 編譯
編譯執(zhí)行應(yīng)用程序時(shí),編譯器會(huì)將加載運(yùn)行時(shí)會(huì)用到的全部代碼. 因?yàn)榫幾g器可以將字節(jié)碼編譯為本地代碼,因此它可以獲取到完整或部分運(yùn)行時(shí)上下文信息,并依據(jù)收集到的信息決定到底應(yīng)該如何編譯字節(jié)碼。
可以對(duì)指令集合進(jìn)行優(yōu)化,優(yōu)化后的指令集合會(huì)被存儲(chǔ)到 code cache 的數(shù)據(jù)結(jié)構(gòu)中,當(dāng)下次執(zhí)行這部分字節(jié)碼序列時(shí),會(huì)執(zhí)行這些經(jīng)過優(yōu)化后被存儲(chǔ)到code cache的指令集合。在某些情況下,性能計(jì)數(shù)器會(huì)失效,并覆蓋掉先前所做的優(yōu)化,這時(shí),編譯器會(huì)執(zhí)行一次新的優(yōu)化過程。
使用code cache的好處是優(yōu)化后的指令集可以立即執(zhí)行.
c. 優(yōu)化
隨著動(dòng)態(tài)編譯器一起出現(xiàn)的是性能計(jì)數(shù)器。
例如,編譯器會(huì)插入性能計(jì)數(shù)器,以統(tǒng)計(jì)每個(gè)字節(jié)碼塊(對(duì)應(yīng)與某個(gè)被調(diào)用的方法)的調(diào)用次數(shù)。 -- 代碼的熱度.
運(yùn)行時(shí)數(shù)據(jù)監(jiān)控有助于編譯器完成多種代碼優(yōu)化工作,進(jìn)一步提升代碼執(zhí)行性能。
轉(zhuǎn)載于:https://www.cnblogs.com/nil2inf/p/4722276.html
總結(jié)
以上是生活随笔為你收集整理的JVM 学习笔记 1. JVM 运行模型的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [转]VMware虚拟机上网络连接(ne
- 下一篇: Sphinx-安装和配置