1. 程式人生 > >JVM(一)運行機制

JVM(一)運行機制

執行 vol defined 觀察 分配 bsp 寄存器 思考 區間

1.啟動流程

技術分享

2.JVM基本結構

技術分享

PC寄存器

  》每個線程擁有一個PC寄存器

  》在線程創建時創建

  》指向下一條指令的地址

  》執行本地方法時,PC的值為undefined

方法區

保存裝載的類的源信息

  》類型的常量池

  》字段、方法信息

  》方法字節碼

  通常和永久區(Perm)關聯在一起

Java

  》和程序開發密切相關

  》應用系統對象都保存在Java堆中

  》所有線程共享Java

  》對分代GC來說,堆也是分代的

  》GC的主要工作區間

Java

  》線程私有

  》棧由一系列幀組成(因此Java棧也叫幀棧)

  》幀保存一個方法的局部變量、操作數棧、常量池指針

  》每一次方法的調用會創建一個幀,並壓棧

1.局部變量表 包含參數和局部變量

技術分享

相對應的局部變量表

技術分享

2.操作數棧

Java沒有寄存器,所有參數傳遞使用操作數棧

技術分享

3.棧上分配

  》小對象(一般幾十個bytes),在沒有逃逸的情況,可以直接分配在棧上

  》直接分配在棧上,可以自動回收,減輕GC壓力

Java內存模型

  》每一個線程有一個工作內存和主存獨立

  》工作內存存放主存中變量的值的拷貝

技術分享

  數據從主內存--->工作內存

    主內存:read 工作內存:load

  數據從工作內存--->主內存

    工作內存:store 主內存:write

  每一個操作都是原子的,即執行期間不會被中斷。

  對於普通變量,一個線程中更新的值,不能馬上反應在其他變量中,如果需要在其它線程中立即可見,需要使用volatile關鍵字。

技術分享

Java的有序性

  》在本線程中,操作都是有序的

  》在線程外觀察,操作都是無序的(指令重排或主內存同步延時)

指令重排:在本線程內不能因執行的順序先後結果發生改變,編譯不考慮多線程

不能重排 a=1,b=a

     a=1,a=2

     a=b,b=1

可以重排 a=1,b=2

synchronized保證有序性

指令重排的基本原則

  》程序順序原則:一個線程內保證語義的串行性

  》volatile規則

  》鎖規則

  》傳遞性

  》線程的start()方法優先於它的每一個動作

  》線程的所有操作優於線程的終結

  》線程的中斷先於被中斷線程的代碼

  》對象的構造函數執行結束先於finalize()方法

Java中字節碼執行的兩種方式

解釋運行

  》解釋執行以解釋方式運行字節碼

  》解釋執行的意思是:讀一句執行一句

編譯運行(JIT

  》將字節碼編譯成機器碼

  》直接執行機器碼

  》運行時編譯

  》編譯後性能由數量級的提升

問題思考:你能想到有什麽辦法,可以讓一個程序的函數調用層次變的更深。比如,你在一個遞歸調用中,發生了stack的溢出,你可以做哪些方面的嘗試,使系統盡量不溢出?闡述你的觀點和原因。

答:

首先了解到線程在調用每個方法的時候,都會創建相應的棧,在退出方法的時候移出棧楨,並且棧是私用的,也需要占用空間,所以讓一個程序的函數調用層次變的更深
減少棧占的空間很必要。或者增大線程的線的大小。
通過volatile增加調用層次深度。線程會對一個沒有volatile的變量進行臨時存儲,這就導致線程棧的空間增大,如果對一個變量增加volatile修飾,可以適當增加深度。

JVM(一)運行機制