成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

了解JVM的結構,好在面試時吹牛

云計算 虛擬化
在一個線程執行的任何時刻,都只會有一個幀是處于激活的。這個幀被稱為當前幀,與之對應的方法被稱為當前方法,方法所在的類被稱為當前類,此時用到的本地變量數組和操作數棧也都是當前幀的。

[[286442]]

jvm包括兩種數據類型,基本類型和引用類型。

基本類型包括,數值類型,boolean類型,和returnAddress類型。

數值類型包括,整型,浮點型,和char類型。

boolean類型同樣只有true和false。

returnAddress類型是一個指針,指向jvm指令的操作碼,在Java中沒有與之對應的類型。

boolean類型的操作會被轉化為int類型的操作進行,boolean數組會當成byte數組去操作。1表示true,0表示false。

引用類型包括三種,類類型,數組類型,和接口類型。

它們的值是動態創建的類實例,數組,或實現接口的類實例。

數組有component類型和element類型,component類型就是數組去掉最外層維度后剩下的類型,可能還是一個數組類型(對于多維數組)。

element類型就是數組里面存儲的最小數據的類型,它必須是一個基本類型,類類型,或接口類型。

對于一維數組的話,component類型和element類型是相同的。

引用類型還有一個特殊值,就是null,表示沒有引用任何對象。

運行時公有數據區

jvm有一個堆,在所有jvm線程間共享,堆是一個運行時數據區域,所有為類實例和數組分配的內存都來自于它。

堆在jvm啟動時創建,堆中對象不用顯式釋放,gc會幫我們釋放并回收內存。

方法區

jvm有一個方法區,在所有jvm線程間共享,它存儲每一個類的結構。

像運行時常量池,字段和方法數據,方法和構造函數的代碼,還有特殊的方法用于類和實例的初始化,以及接口的初始化。

方法區在jvm啟動時創建,雖然方法區在邏輯上是堆的一部分。

但簡單實現時可以選擇不進行gc和壓縮,本規范沒有強制要求方法區的位置,也沒有要求管理已編譯代碼的策略。

運行時常量池

運行時常量池就是類或接口的字節碼文件里的常量池的運行時表示形式,它包含幾種常量。

如在編譯時就已經知道的數字字面量值,和必須在運行時解析的方法和字段的引用,運行時常量池的功能類似于傳統語言的符號表,不過它包含的數據會更加寬泛。

運行時常量池分配在jvm的方法區,類或接口的運行時常量池在類或接口被jvm創建時才會構建。

運行時私有數據區

pc寄存器

jvm支持一次運行多個線程,每個線程都有自己的pc寄存器,任何時候一個線程只能運行一個方法的代碼。

如果方法不是native的,pc寄存器包含當前正在被執行的jvm指令地址,如果方法是native的,pc寄存器的值是未定義的。

jvm棧

每一個jvm線程都有一個私有的jvm棧,隨著線程的創建而創建,棧中存儲的是幀。

jvm棧和傳統語言如C的棧相似,保存局部變量和部分計算結果,參與方法的調用和返回。jvm棧主要用于幀的出棧和入棧,除此之外沒有其它操作,

幀可能是在堆上分配的,所以jvm棧使用的內存不必是連續的。

native方法棧

native方法不是用Java語言寫的,為了支持它需要使用傳統棧,如C語言棧。不過jvm不能加載native方法,所以也不需要提供native方法需要的棧。

每次當一個方法被調用時一個新的幀會被創建。當方法調用完成時,與之對應的幀會被銷毀,無論是正常完成還是拋異常結束。

所以幀是方法調用的具體體現形式,或稱方法調用是以幀的形式進行的。幀用來存儲數據和部分計算結果,和執行動態鏈接,方法返回值,分發異常。

幀分配在創建幀的線程的jvm棧上,每一個幀都有自己的本地變量數組,自己的操作數據棧,和一個對當前方法所在類的運行時常量池的引用。

本地變量數組和操作數棧的大小在編譯時就確定了,它們隨著和幀關聯的方法編譯后的代碼一起被提供,因此幀這種數據結構的大小只依賴于jvm的實現,這些結構所需的內存可以在方法調用時同時被分配。

在一個線程執行的任何時刻,都只會有一個幀是處于激活的。這個幀被稱為當前幀,與之對應的方法被稱為當前方法,方法所在的類被稱為當前類,此時用到的本地變量數組和操作數棧也都是當前幀的。

一個幀將不在繼續是當前幀,如果它的方法調用了另一個方法,或者它的方法結束了。

當一個方法被調用,一個新的幀被創建,當執行控制由原來的方法傳遞到新的方法時,這個新的幀變為當前幀。

當方法返回時,當前幀把方法執行的結果傳回到上一幀,當上一幀被激活的同時當前幀會被丟棄。

本地變量數組

每一幀都包含一個變量數組,就是都熟知的本地變量存儲的地方。這個本地變量數組的長度在編譯時確定,隨著編譯后的方法代碼一起提供。

通常一個本地變量(的位置)能夠存儲一個類型的值,但是long和double類型卻需要兩個本地變量(的位置)才能存一個值。

本地變量按索引尋址,第一個本地變量的索引是0。long和double需要消耗兩個連續的索引,但卻是按照較小的這個索引尋址的。不能按照較大的那個索引去讀數據,但是可以寫入,當然這樣將使本地變量內容錯亂。

在方法被調用時,jvm使用本地變量來接收傳遞進來的參數值。在類(靜態)方法調用時,所有參數被傳入從索引0開始的連貫的本地變量數組里。

在實例(非靜態)方法調用時,索引0處總是傳入正在其上執行方法調用的那個對象的引用,(就是Java中的this了),所有參數被傳入從1開始的連貫的本地變量數組里。

操作數棧

每個幀包含一個后進先出的棧,用于存儲正在執行的jvm指令的操作數,就是都熟知的操作數棧,這個棧的最大深度在編譯時就已確定,隨著編譯后的方法代碼一起提供。

當幀被創建時,操作數棧是空的,jvm提供一些指令用于加載常量值,本地變量值,字段值到操作數棧上,另一些jvm指令采用操作數棧上的操作數進行操作,并把結果放回到操作數棧上。

操作數棧也用于準備將要傳遞給方法調用的參數和接收方法調用返回的結果。

long和double類型的值占用兩個單位的棧深度,其它類型的值占用一個單位的棧深度。

動態鏈接

每一個幀都包含了對當前方法所屬類型的運行時常量池的引用。目的是為了支持方法代碼的動態鏈接。class文件中描述一個方法引用被調用的方法和被訪問的變量的代碼,是采用符號引用的形式實現的。

符號引用的形式可以粗略的認為是字符串的形式,就是用字符串標明需要調用哪個類的哪個方法或訪問哪個字段或變量。就像符號引用這個名字一樣,這些僅僅是符號,是拿不到具體值的,所以必須要進行轉換。

動態鏈接就是把這些符號方法引用轉換為具體的方法引用,在必要時加載類來解析尚未明確的符號,把符號變量的訪問轉換為這些變量運行時所在存儲結構的適合的偏移量(索引)。這樣的方式又稱為后期綁定。

方法調用

一個方法調用正常完成(即沒有拋異常)時,會根據所返回的值的類型執行一個適合的return指令,當前幀會去恢復調用者的狀態,包括它的本地變量和操作數棧,使調用者的程序計數器適合的遞增來跳過剛剛的那個方法調用指令。

返回值會被放到調用者幀的操作數棧上,然后繼續執行調用者方法的幀。

一個方法在調用時拋出了異常,且這個異常沒有在這個方法內被捕獲處理,將會導致這個方法調用的突然結束,這種情況下永遠不會向方法的調用者返回一個值。

特殊方法

站在jvm的級別,每一個用Java寫的構造函數都以一個實例初始化方法出現,且都是特殊的名字,就是,這個名字是編譯器提供的。

實例初始化方法只能在jvm內部使用invokespecial這個指令調用,且只能在尚未初始化的類實例上調用。

一個類或接口最多可以有一個類或接口初始化方法,通過調用這個方法被初始化。類或接口的初始化方法也有特殊的名字,就是,該方法沒有參數,且返回值是void。

方法名稱也是由編譯器提供的,從Java7開始,在字節碼中這個方法必須被標記為靜態的才行。

這個初始化方法是被jvm隱式調用的,它們絕對不會直接被用任何jvm指令調用,僅作為類初始化進程的一部分被間接的調用。

Java類庫

jvm必須為Java類庫的實現提供足夠的支持。一些類庫中的類如果沒有jvm協助是無法實現的。

反射,就是在運行時獲取某個類的類型相關信息,如它的字段信息,方法信息,構造函數信息,父類信息,實現的接口信息。

這些信息都必須是把一個類加載完之后才可以知道的,只有jvm才可以加載類。如java.lang.reflect這個包下的類和Class這個類。

在Java中加載一個類或接口用類加載器,即ClassLoader,背后還是委托給jvm來實現的。

鏈接和初始化一個類或接口。

安全,如java.security包下的類,還有其它類像SecurityManager。

多線程,如線程這個類Thread。

弱引用,像java.lang.ref包下的類。

公有設計,私有實現

以上內容只是jvm的一個“相對寬泛”的規范,它并不是實現方案,也不是實現細節。

實現者可以根據自身的需要來實現jvm,如運行在后端服務器上的jvm和運行在移動設備上的jvm肯定側重點有所不同。

從事Java的人都知道,事實上jvm是有較多的實現版本。

由于jvm是處在Java語言和操作系統之間的,所以它要向上提供對Java的支持,向下與操作系統良好交互。

寫在最后

高級語言(Java,C#)中的很多操作如文件操作,網絡操作,內存操作,線程操作,I/O操作等,都不是高級語言自身能夠實現的。

也不是它們的虛擬機(JVM,CLR)能夠實現的,實際最終是由操作系統實現的,因為這些都是系統資源,只有操作系統才有權限訪問。

如果你用Java或C#代碼創建了一個文件,千萬不要以為是Java或C#創建了這個文件,它們只是層層向下調用了操作系統的API,然后到文件系統API,最后可能到磁盤驅動程序。

由此可以看出,要想設計一門語言,不單單是關鍵字、語法、編譯器,類庫,虛擬機這些,還要深度了解操作系統,甚至是硬件,如CPU架構和CPU指令集等。

所以,和語言相關的事情,每一項都是異常的繁瑣復雜,都需要投入大量的人力、財力、時間去研究,最后即使研究成功了,可能沒有生態,沒人使用,自然也無法賺錢。

因此,國人現在還沒有一門屬于自己的真正語言。

責任編輯:武曉燕 來源: 編程新說
相關推薦

2010-08-10 16:21:48

面試薪資

2012-08-20 14:09:29

面試

2010-08-09 16:30:53

面試

2010-11-09 10:24:46

面試

2022-01-10 06:53:00

JVM 面試Java

2009-02-27 10:30:09

面試聯想智力

2010-09-27 09:31:42

JVM內存結構

2022-04-30 08:09:37

面試開發閱讀源碼

2010-08-04 14:11:58

面試木訥

2012-12-28 15:53:53

面試應屆畢業生

2010-04-20 14:59:56

面試

2010-07-20 15:52:01

面試

2021-06-21 07:44:07

程序員面試職場

2012-08-23 09:44:32

面試面試題算法

2014-08-13 09:47:17

面試

2020-10-26 08:55:52

Redis單線程模型

2010-06-09 11:20:53

求職者面試

2011-03-01 09:36:26

面試算法解題思路

2014-08-14 10:19:01

程序員

2018-06-27 13:10:22

程序員面試易犯錯誤
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 作爱视频免费看 | 激情a| 欧美一区二不卡视频 | 久久噜噜噜精品国产亚洲综合 | 日韩成人av在线 | 亚洲xxxxx | 日韩精品一区二区三区中文字幕 | 欧美影院 | 免费一区在线观看 | 国产精品日产欧美久久久久 | 天天操一操 | 中文字幕一级毛片视频 | 一级全黄视频 | 国产精品一二三区 | 看片wwwwwwwwwww| 亚洲女优在线播放 | 羞羞网站在线观看 | 国产9久 | 国产欧美日韩综合精品一 | 欧美一级在线观看 | 精品网站999 | 国产精品电影网 | 国产日韩欧美 | 在线观看黄色大片 | 欧美精品欧美精品系列 | av入口| 日韩免费在线视频 | 亚洲国产高清免费 | 欧美成人精品在线观看 | 国产精品美女一区二区三区 | 欧美一区二区三区四区视频 | h小视频 | 中文字幕在线一区二区三区 | 亚洲二区视频 | 在线观看久草 | 亚洲狠狠爱 | 看a网站 | 91一区二区 | 最新日韩av | 欧美一区二区三区在线免费观看 | 欧美三级成人理伦 |