麻豆成人91精品二区三区,国产91在线播放,加勒比无码专区中文字幕,欧美黑人XXXX高潮猛交

×
新網 > 虛擬主機 > 正文

深入理解Java之java虛擬機干凈利落的規(guī)范總結 上

  • 作者:新網
  • 來源:新網
  • 瀏覽:100
  • 2018-05-03 17:57:51

要去正確地實現(xiàn)一臺Java虛擬機,就需要正確地讀取class文件中每一條字節(jié)碼指令并且能正確執(zhí)行這些指令所蘊含的操作即可。

   hosting.jpg

<div>  要去正確地實現(xiàn)一臺Java虛擬機,就需要正確地讀取class文件中每一條字節(jié)碼指令并且能正確執(zhí)行這些指令所蘊含的操作即可。
  數據類型
  和Java語言類似,在Java虛擬機中的數據類型也可以分為基本類型和引用類型兩種,所以也存在原始值和引用值兩種類型的數值。它們可用于變量賦值、參數傳遞、方法返回和運算操作。
  原始類型與值
  Java虛擬機所支持的原始數據類型包括數值類型、boolean類型、和returnAddress類型
  數值類型分為整數類型和浮點類型,分別是char,byte,short,int,long;浮點類型即float和double,這里和Java語言中的一致。
  returnAddress翻譯過來是返回地址,其實returnAddress類型的值指向一條虛擬機指令的操作碼。它在虛擬機中比較典型的一個應用場景是用于jsr程序段落跳轉,在try-catch異常處理以及finally代碼塊經常出現(xiàn)。和數值類的原生類型不同,returnAddress類型在Java語言之中并不存在相應的類型,而且也無法在程序運行期間修改。
  雖然Java虛擬機定義了boolean這種數據類型,但是只對它提供了十分有限的支持。在Java虛擬機中并沒有任何供boolean值專用的字節(jié)碼指令,Java語言表達式所操作的boolean值,在編譯之后都使用Java虛擬機中的int數據類型來代替。(Java虛擬機會把boolean數組元素中的true采用1來表示,false采用0來表示,當Java編譯器把Java語言中的boolean類型值映射為Java虛擬機的int類型值時,也必須用上述表示方式)
  引用類型與值
  Java虛擬機中有三種引用類型:類類型、數組類型和接口類型。它們分別指向動態(tài)創(chuàng)建的類實例、數組實例和某個接口的類實例或數組實例。
  數組類型最外面那一維元素的類型叫做數組類型的組件類型。一個數組的組件類型也可以是數組。從任意一個數組開始,如果發(fā)現(xiàn)其組件類型也是數組類型,那就繼續(xù)取這個小數組的組件類型,不斷執(zhí)行這樣的操作,最終一定可以遇到組件類型不是數組的情況,這時就把這種類型成為本數組的元素類型。數組的元素類型必須是原生類型、類類型或者接口類型之一。
  在引用類型的值中還有一個特殊的值:null,當一個引用不指向任何對象的時候,它的值就用null來表示。一個為null的引用,起初并不具備任何實際的運行期類型,但是它可轉型為任意的引用類型。引用類型的默認值就是null。Java虛擬機規(guī)范并沒有規(guī)定null在虛擬機實現(xiàn)中應當怎樣用編碼來表示。
  運行時數據區(qū)域
  棧幀:棧幀是用來存儲數據和部分過程結果的數據結構,同時也用來處理動態(tài)鏈接、方法返回值和異常分派。棧幀又是存儲在棧中(包括Java虛擬機棧和本地方法棧),它隨著方法調用而創(chuàng)建,隨著方法結束而銷毀,其實也就是一個方法執(zhí)行的過程也對應著棧幀的入棧和出棧的過程。無論方法是正常完成還是異常完成(拋出了在方法內未被捕獲的異常)都算作方法結束。棧幀的存儲空間由創(chuàng)建它的線程分配在Java虛擬機棧之中,每一個棧幀都有自己的本地變量表、操作數棧和指向當前方法所屬的類的運行時常量池的引用。
  本地變量表和操作數棧的容量在編譯期確定,并通過相關方法的code屬性保存及提供給棧幀使用。因此,棧幀數據結構的大小僅僅取決于Java虛擬機的實現(xiàn)。實現(xiàn)者可以在調用方法的時候給它們分配內存。
  在某條線程執(zhí)行的過程中的某個時間點,只有目前正在執(zhí)行的那個方法的棧幀是活動的。這個棧幀稱為當前棧幀,這個棧幀對應的方法稱為當前方法,定義這個方法的類稱作當前類。對局部變量表和操作數棧的各種操作,通常都是值對當前棧幀的局部變量表和操作數棧所進行的操作。
  如果當前方法調用了其他方法,或者當前方法執(zhí)行結束,那這個方法的棧幀就不再是當前棧幀了。調用新方法時,新的棧幀也會隨之而創(chuàng)建,并且會隨著程序控制權移交到新方法而成為新的當前棧幀。方法返回之際,當前棧幀會傳回此方法給前一個棧幀,然后虛擬機會丟棄當前棧幀,使得前一個棧幀重新成為當前棧幀。
  需要特別注意的是,棧幀是線程本地私有的數據,不可能在一個棧幀之中引用另外一個線程的棧幀。
  局部變量表
  每個棧幀內部都包含一組稱為局部變量表的變量列表。棧幀中局部變量表的長度由編譯器決定,并卻存儲于類或接口的二進制表示之中,即通過方法的code屬性保存及提供給棧幀使用。
  一個局部變量可以保存一個類型為boolean、byte、char、short、int、float、reference或returnAddress的數據。兩個局部變量可以保存一個類型為long或double的數據。
  局部變量使用索引來進行定位訪問。首個局部變量的索引值為0。局部變量的索引值是個整數,它大于等于0,且小于局部變量表的長度。Java虛擬機使用局部變量表來完成方法調用時的參數傳遞。當調用類方法時,它的參數將會依次傳遞到局部變量表中從0開始的連續(xù)位置上。當調用實例方法時,第0個局部變量一定用來存儲該實例方法所在對象的引用(即Java語言中的this關鍵字)。后續(xù)其他參數將會傳遞至局部變量表中從1開始的連續(xù)位置上。
  操作數棧:每個棧幀內部都包含一個稱為操作數棧的后進后出棧。棧幀中操作數棧的最大深度由編譯期決定,并且通過方法的code屬性保存及提供給棧幀使用。棧幀剛創(chuàng)建的時候操作數棧是空的。Java虛擬機提供一些字節(jié)碼指令來從局部變量表或者對象實例的字段中復制常量或變量值到操作數棧中,也提供了一些指令用于從操作數棧取走數據、操作數據以及把操作結果重新入棧。在調用方法時,操作數棧也用來準備調用方法的參數以及接收方法返回結果。例如iadd字節(jié)碼指令的作用是將兩個int類型的數值相加,它要求在執(zhí)行之前操作數棧的棧頂已經存在兩個由前面的其他指令所放入的int類型數值。在執(zhí)行iadd指令時,兩個int類型數值出棧,相加求和之后求和結果重新入棧。操作數棧的每個位置上可以保存一個Java虛擬機中定義的數據類型的值,包括long和double類型。在任意時刻,操作數棧都會有一個確定的棧深度,一個long或者double類型的數據會占用兩個單位的棧深度,其他數據類型則會占用一個單位的棧深度。
  動態(tài)鏈接
  每個棧幀內部都包含一個指向當前方法所在類型的運行時常量池的引用,以便對當前方法的代碼實現(xiàn)動態(tài)鏈接。在class文件里面一個方法若要調用其他方法,或者訪問成員變量,則需要通過符號引用來表示。動態(tài)鏈接的作用就是將這些符號引用所表示的方法轉換為對實際方法的直接引用。類加載的過程中將要解析尚未被解析的符號引用,并且將對變量的訪問轉化為變量在程序運行時,位于存儲結構中的正確偏移量。由于對其他類中的方法和變量進行了晚期綁定,所以即便那些類發(fā)生變化,也不會影響調用它們的方法。
  對象的表示
  Java虛擬機規(guī)范不強制規(guī)定對象的內部結構應該如何表示。在具體實現(xiàn)中,一般有兩種對象的訪問方式,分別是通過句柄訪問對象以及通過直接指針訪問對象。
  在之前的博客里我也總結過這兩種對象訪問方式的優(yōu)劣,想要了解的同學可以參考這篇博客
  特殊方法
  在Java虛擬機層面,Java編程語言的構造器是以一個名為的特殊實例初始方法的形式出現(xiàn)的。這個方法名稱是由編譯器命名的,因為它并非一個合法的Java方法名字,不可能通過程序編碼的方式實現(xiàn)。實例初始化方法的初始化期間,通過Java虛擬機的invokespecial指令來調用,而且只能在尚未初始化的實力上調用該指令。構造器的訪問權限也會約束由該構造器所衍生出來的實例初始化方法。
  一個類或者接口最多可以包含不超過一個類或接口的初始化方法,類或接口就是通過這個方法完成初始化的。這個方法是一個不包含參數的、返回類型為void的方法,名為。
  在class文件中把其他方法命名為是沒有意義的,這些方法并不是類或接口的初始化方法,它們既不能被字節(jié)碼指令調用,也不會被虛擬機自己調用。當class文件的版本號不小于51.0時,方法想要成為類或接口的初始化方法,必須設置ACC_STATIC標志。
  異常
  Java虛擬機里面的異常使用Throwable或其子類的實例來表示,拋異常的本質實際上是程序控制權轉移的一種即時的、非局部的轉換---從異常拋出的地方轉換至異常處理的地方。
  絕大多數異常的產生都是由于當前線程執(zhí)行的某個操作所導致的,這種可以稱為同步異常。與之相對,異步異常可以在程序執(zhí)行過程中隨時發(fā)生。Java虛擬機中異常的出現(xiàn)總是由下面三種原因之一導致的:
  athrow字節(jié)碼指令被執(zhí)行;
  虛擬機同步檢測到程序發(fā)生了非正常的執(zhí)行情況,這時異常必將緊接著發(fā)生在非正常執(zhí)行情況的字節(jié)碼指令之后拋出,而不會在執(zhí)行程序的過程中隨時拋出。例如:程序所執(zhí)行的操作可能會引發(fā)異常---當字節(jié)碼指令所蘊含的操作違反了Java語言的語義,如訪問一個超出數組邊界范圍的元素,或者是當程序在加載或者連接時出現(xiàn)錯誤;還有一種異常是使用某些資源的時候產生資源限制,比如說使用了太多的內存。
  由于以下原因,導致了異步異常的發(fā)生: 調用了Thread或者ThreadGroup的stop方法;Java虛擬機實現(xiàn)發(fā)生了內部錯誤。
  當某個線程調用了stop方法時,將會影響到其他線程,或者在特定線程組中的所有線程。因為stop方法的執(zhí)行常常會導致出現(xiàn)數據不一致的情況,這時候其他線程中出現(xiàn)的異常就是異步異常,因為這些異??赡艹霈F(xiàn)在線程執(zhí)行過程中的任何位置。虛擬機的內部錯誤也被認為是一種異步異常。
  虛擬機錯誤
  InternalError:實現(xiàn)虛擬機的軟件錯誤、底層主機系統(tǒng)的軟件錯誤及硬件錯誤都會導致Java虛擬機出現(xiàn)內部錯誤,InternalError是一個異步異常,它可能出現(xiàn)在程序中的任何位置;
  OutOfMemoryError:當Java虛擬機實現(xiàn)耗盡了所有虛擬或物理內存,并且內存自動管理子系統(tǒng)無法回收到創(chuàng)建新對象所需的足夠內存空間時,虛擬機將拋出OutOfMemoryError。
  StackOverflowError:當Java虛擬機實現(xiàn)耗盡了線程全部的棧空間時,虛擬機將會拋出StackOverflowError。
  UnKnownError:當某種錯誤或異常出現(xiàn),但虛擬機實現(xiàn)又無法確定它具體是哪種異?;蝈e誤,將會拋出UnKnownError。
  由于通常虛擬機會對代碼進行優(yōu)化,例如指令重排。那么在異常發(fā)生的時候,有一些在異常出現(xiàn)位置之后的代碼可能已經執(zhí)行了,那這些優(yōu)化過的代碼必須保證它們提前執(zhí)行所產生的影響對用戶程序來說是不可見的。
 

免責聲明:本文內容由互聯(lián)網用戶自發(fā)貢獻自行上傳,本網站不擁有所有權,也不承認相關法律責任。如果您發(fā)現(xiàn)本社區(qū)中有涉嫌抄襲的內容,請發(fā)送郵件至:operations@xinnet.com進行舉報,并提供相關證據,一經查實,本站將立刻刪除涉嫌侵權內容。

免費咨詢獲取折扣

Loading
亚洲欧美一本一道久久| av热热热| 欧美日韩看黄片在线| 日本一区二区极品视频| 九九九中文| 美日韩中文字幕| 精品国产成人XXXX| AV一区av一区色色| 中文字幕乱偷无码动漫av| 久久电影一区二区三区| 无码不卡小视频| 最近免费中文mv在线字幕| 香蕉网天天日夜夜操| 日韩一区二区扒开下体| 欧美成人高清精品免费| 无码激情久久| 欧美国产精品区| 久久99久久99精品免视看| 插插插亚洲| 国产欧美日韩天堂| 国产精品免费观看| 北岛玲一区| av在线插| 亚洲精品偷拍| 亚洲日韩字幕| 91yeyecao| 911亚洲精品| 被两个两个黑人吃奶4P| 国产在线观看中| 欧美丰满熟妇XXXX性ppX人交| 欧美日韩无线码一区| 久久久久99精品成人片试看| 另类h视频| 欧美日韩人人妻| 99久久免费国产精品| 大香网综合| 中文字幕组一区二区| 加勒比无码专区中文字幕| 亚洲男人天堂久久| 日韩青椒AV无码二区| AV色综合久久天堂AV色综合在|