JVM-Java字節(jié)碼

Java是一種面向?qū)ο蟮模o態(tài)類型的苛谷,需要編譯執(zhí)行的語言。運(yùn)行在Java虛擬機(jī)上瓢湃,并提供了自動(dòng)的垃圾回收機(jī)制赫蛇。

編程語言跨平臺的方式:

源代碼跨平臺:

源代碼跨平臺

二進(jìn)制跨平臺:

二進(jìn)制跨平臺

字節(jié)碼落蝙,類加載器,虛擬機(jī)的關(guān)系:

關(guān)系圖

Java將源代碼移迫,通過javac編譯器將代碼編譯成字節(jié)碼.class文件厨埋,在執(zhí)行java命令捐顷,將.class文件加載到虛擬機(jī)中迅涮,通過虛擬機(jī)的類加載器加載成類的實(shí)例,并保存在內(nèi)存中唉地,供運(yùn)行時(shí)使用传透。

字節(jié)碼(Java bytecode)實(shí)際上是由單字節(jié)(byte)的指令組成旷祸,理論上最多支持256個(gè)操作碼(opcode)托享,JVM虛擬機(jī)像計(jì)算機(jī)一樣按字節(jié)碼指令去執(zhí)行它。

  1. 棧操作指令赃绊,包括與局部變量交互的指令
  2. 程序流程控制指令
  3. 對象操作指令羡榴,包括方法調(diào)用指令
  4. 算術(shù)運(yùn)算以及類型轉(zhuǎn)換指令

算術(shù)操作與類型轉(zhuǎn)換操作碼:

操作碼

方法調(diào)用指令:

  • invokestatic忠售,顧名思義迄沫,這個(gè)指令用于調(diào)用某個(gè)類的靜態(tài)方法,這是方法調(diào)用指令中最 快的一個(gè)泰佳。
  • invokespecial, 用來調(diào)用構(gòu)造函數(shù),但也可以用于調(diào)用同一個(gè)類中的 private 方法, 以及 可見的超類方法浇坐。
  • invokevirtual近刘,如果是具體類型的目標(biāo)對象宁昭,invokevirtual 用于調(diào)用公共积仗,受保護(hù)和 package 級的私有方法蜕猫。
  • invokeinterface,當(dāng)通過接口引用來調(diào)用方法時(shí)隆圆,將會(huì)編譯為 invokeinterface 指令渺氧。
  • invokedynamic蹬屹,JDK7 新增加的指令,是實(shí)現(xiàn)“動(dòng)態(tài)類型語言”(Dynamically Typed Language)支持而進(jìn)行的升級改進(jìn)贩耐,同時(shí)也是 JDK8 以后支持 lambda 表達(dá)式的實(shí)現(xiàn)基 礎(chǔ)厦取。

由于Java虛擬機(jī)是基于字節(jié)碼指令執(zhí)行的,所以理論上Java虛擬機(jī)提供了語言無關(guān)性的能力铡买,他所能提供的語言描述能力也要比Java語言本身更加強(qiáng)大寻狂。

語言無關(guān)性

如何生成字節(jié)碼蛇券?

通過javac指令,編譯源代碼塘慕,在通過javap -c指令查看字節(jié)碼图呢。

image.png

所有的計(jì)算都是在棧上蛤织,但是我們變量的名字和變量的值指蚜,都在本地變量表里涨椒。

JVM是模擬一臺基于棧的計(jì)算機(jī),每個(gè)線程都有獨(dú)屬于自己的線程棧(JVM Stack)免猾,用于存儲棧幀(Frame)猎提。每個(gè)方法調(diào)用旁蔼,JVM都會(huì)自動(dòng)創(chuàng)建一個(gè)棧幀牌芋。棧幀由操作數(shù)棧(Operand Stack),局部變量數(shù)組(Local variables)以及一個(gè)Class引用組成肯夏。Class引用指向當(dāng)前方法在運(yùn)行時(shí)常量池中對應(yīng)的Class驯击。

image.png

Demo例子:

public class Demo{
    public static void foo(){
        int a = 1;
        int b = 2;
        int c = (a + b) * 5;
    }
}

Demo的反編譯文件信息: java -c -v Demo

Classfile /Users/kuaikan/Demo.class
  Last modified 2021-2-17; size 249 bytes
  MD5 checksum 23df48a1e96791ecfac2821b402e530e
  Compiled from "Demo.java"
public class Demo
  minor version: 0
  major version: 52
  flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
   #1 = Methodref          #3.#11         // java/lang/Object."<init>":()V
   #2 = Class              #12            // Demo
   #3 = Class              #13            // java/lang/Object
   #4 = Utf8               <init>
   #5 = Utf8               ()V
   #6 = Utf8               Code
   #7 = Utf8               LineNumberTable
   #8 = Utf8               foo
   #9 = Utf8               SourceFile
  #10 = Utf8               Demo.java
  #11 = NameAndType        #4:#5          // "<init>":()V
  #12 = Utf8               Demo
  #13 = Utf8               java/lang/Object
{
  public Demo();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Object."<init>":()V
         4: return
      LineNumberTable:
        line 1: 0

  public static void foo();
    descriptor: ()V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=3, args_size=0
         0: iconst_1
         1: istore_0
         2: iconst_2
         3: istore_1
         4: iload_0
         5: iload_1
         6: iadd
         7: iconst_5
         8: imul
         9: istore_2
        10: return
      LineNumberTable:
        line 3: 0
        line 4: 2
        line 5: 4
        line 6: 10
}

代碼動(dòng)態(tài)執(zhí)行的例子:

jvmstack.gif

通過上面的gif圖可以看出,foo方法只需要用到椣窘茫空間為2,局部變量表為3槽奕,正好對應(yīng)反編譯出來的房轿,foo方法中的Code部分囱持,stack=2纷妆,locals=3這里。

所以我們可以看出问欠,代碼在編譯之后粒蜈,實(shí)際上已經(jīng)可以確定當(dāng)前方法的椏莶溃空間大小以及局部變量表大小度硝。

從助記符到二進(jìn)制:

在.class文件中都是大量的二進(jìn)制code寿冕,javap相當(dāng)于將二進(jìn)制文件翻譯成可讀的形式輸出出來驼唱。

image.png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末辨赐,一起剝皮案震驚了整個(gè)濱河市京办,隨后出現(xiàn)的幾起案子掀序,更是在濱河造成了極大的恐慌呀邢,老刑警劉巖仔蝌,帶你破解...
    沈念sama閱讀 210,978評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡濒翻,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,954評論 2 384
  • 文/潘曉璐 我一進(jìn)店門闷串,熙熙樓的掌柜王于貴愁眉苦臉地迎上來享扔,“玉大人,你說我怎么就攤上這事式散〗钤猓” “怎么了?”我有些...
    開封第一講書人閱讀 156,623評論 0 345
  • 文/不壞的土叔 我叫張陵暴拄,是天一觀的道長。 經(jīng)常有香客問我响驴,道長,這世上最難降的妖魔是什么琳骡? 我笑而不...
    開封第一講書人閱讀 56,324評論 1 282
  • 正文 為了忘掉前任炫狱,我火速辦了婚禮,結(jié)果婚禮上酷含,老公的妹妹穿的比我還像新娘陆爽。我一直安慰自己别威,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,390評論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般坑鱼。 火紅的嫁衣襯著肌膚如雪耕魄。 梳的紋絲不亂的頭發(fā)上阐枣,一...
    開封第一講書人閱讀 49,741評論 1 289
  • 那天逞度,我揣著相機(jī)與錄音揖赴,去河邊找鬼渐北。 笑死恃锉,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 38,892評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼敌呈,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了鲫咽?” 一聲冷哼從身側(cè)響起歹嘹,我...
    開封第一講書人閱讀 37,655評論 0 266
  • 序言:老撾萬榮一對情侶失蹤卑吭,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后己单,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,104評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,451評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,569評論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡啸驯,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤撤蟆,帶...
    沈念sama閱讀 34,254評論 4 328
  • 正文 年R本政府宣布式镐,位于F島的核電站辆亏,受9級特大地震影響扮叨,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,834評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸漾稀。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,725評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至荸实,卻和暖如春露氮,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背三妈。 一陣腳步聲響...
    開封第一講書人閱讀 31,950評論 1 264
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人握联。 一個(gè)月前我還...
    沈念sama閱讀 46,260評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像每瞒,于是被迫代替她去往敵國和親金闽。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,446評論 2 348

推薦閱讀更多精彩內(nèi)容