JVM匯編總結(jié)

無(wú)關(guān)性的基石

計(jì)算機(jī)只認(rèn)識(shí)0和1官还,所以我們寫的程序需要被編譯器翻譯成0和1才能被計(jì)算機(jī)執(zhí)行屯伞。10多年的時(shí)間過(guò)去了,今天的計(jì)算機(jī)仍然只識(shí)別0和1,但由于最近10年內(nèi)虛擬機(jī)及建立在虛擬機(jī)之上的大量程序語(yǔ)言如后春筍般出現(xiàn)并蓬勃發(fā)展滑潘,將我們編寫字的程序編譯成二進(jìn)制本地機(jī)器碼已經(jīng)不再是唯一的選擇,越來(lái)越多的程序語(yǔ)言選擇了與操作系統(tǒng)和機(jī)器指令集無(wú)關(guān)的钮孵,平臺(tái)中立的格式作為程序編譯后的存儲(chǔ)格式荧库。“一次編寫,到處運(yùn)行”竿裂。

JAVA 虛擬機(jī)規(guī)范
https://docs.oracle.com/javase/specs/jvms/se11/html/index.html

JAVA 語(yǔ)言規(guī)范
https://docs.oracle.com/javase/specs/jls/se11/html/index.html

java虛擬機(jī)提供的平臺(tái)無(wú)關(guān)性

概念

字節(jié)碼

即JAVA源文件編譯后的字節(jié)碼文件影斑,文件格式內(nèi)容<<深入理解java 虛擬機(jī)>> 第六章類文件格式,有詳細(xì)講解.包括JVM匯編指令.字節(jié)碼與JVM匯編助記符見<<深入理解JAVA虛擬機(jī)>>附錄B

匯編

JAVA語(yǔ)言的運(yùn)行時(shí)匯編為AT&T匯編,詳見下文
http://www.reibang.com/p/74d54c9d818d

volatile 關(guān)鍵字可見性分析實(shí)例

javap 指令可以反JVM匯編

用法: javap <options> <classes>
其中, 可能的選項(xiàng)包括:
  -help  --help  -?        輸出此用法消息
  -version                 版本信息
  -v  -verbose             輸出附加信息
  -l                       輸出行號(hào)和本地變量表
  -public                  僅顯示公共類和成員
  -protected               顯示受保護(hù)的/公共類和成員
  -package                 顯示程序包/受保護(hù)的/公共類
                           和成員 (默認(rèn))
  -p  -private             顯示所有類和成員
  -c                       對(duì)代碼進(jìn)行反匯編
  -s                       輸出內(nèi)部類型簽名
  -sysinfo                 顯示正在處理的類的
                           系統(tǒng)信息 (路徑, 大小, 日期, MD5 散列)
  -constants               顯示最終常量
  -classpath <path>        指定查找用戶類文件的位置
  -cp <path>               指定查找用戶類文件的位置
  -bootclasspath <path>    覆蓋引導(dǎo)類文件的位置

JAVA源代碼

public class VolitaleTest {
    private static volatile int i = 0;
    public static void main(String[] args) {
        i++;
    }
}

查看JAVA class文件字節(jié)碼,注意,這里是JVM匯編指令,并非運(yùn)行時(shí)匯編

Classfile /D:/sparrow/sparrow-shell/sparrow-test/target/test-classes/com/sparrow/jdk/volatilekey/VolitaleTest.class
  Last modified 2018-10-4; size 527 bytes
  MD5 checksum 51ad6d8677911aedc21bf4e1a5ea7343
  Compiled from "VolitaleTest.java"
public class com.sparrow.jdk.volatilekey.VolitaleTest
  minor version: 0
  major version: 52
  flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
   #1 = Methodref          #4.#21         // java/lang/Object."<init>":()V
   #2 = Fieldref           #3.#22         // com/sparrow/jdk/volatilekey/VolitaleTest.i:I
   #3 = Class              #23            // com/sparrow/jdk/volatilekey/VolitaleTest
   #4 = Class              #24            // java/lang/Object
   #5 = Utf8               i
   #6 = Utf8               I
   #7 = Utf8               <init>
   #8 = Utf8               ()V
   #9 = Utf8               Code
  #10 = Utf8               LineNumberTable
  #11 = Utf8               LocalVariableTable
  #12 = Utf8               this
  #13 = Utf8               Lcom/sparrow/jdk/volatilekey/VolitaleTest;
  #14 = Utf8               main
  #15 = Utf8               ([Ljava/lang/String;)V
  #16 = Utf8               args
  #17 = Utf8               [Ljava/lang/String;
  #18 = Utf8               <clinit>
  #19 = Utf8               SourceFile
  #20 = Utf8               VolitaleTest.java
  #21 = NameAndType        #7:#8          // "<init>":()V
  #22 = NameAndType        #5:#6          // i:I
  #23 = Utf8               com/sparrow/jdk/volatilekey/VolitaleTest
  #24 = Utf8               java/lang/Object
{
  public com.sparrow.jdk.volatilekey.VolitaleTest();
    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 15: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       5     0  this   Lcom/sparrow/jdk/volatilekey/VolitaleTest;

  public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=1, args_size=1
         0: getstatic     #2                  // Field i:I
         3: iconst_1
         4: iadd
         5: putstatic     #2                  // Field i:I
         8: return
      LineNumberTable:
        line 18: 0
        line 19: 8
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       9     0  args   [Ljava/lang/String;

  static {};
    descriptor: ()V
    flags: ACC_STATIC
    Code:
      stack=1, locals=0, args_size=0
         0: iconst_0
         1: putstatic     #2                  // Field i:I
         4: return
      LineNumberTable:
        line 16: 0
}
SourceFile: "VolitaleTest.java"

以上內(nèi)容與CLASS文件描述格式一致.

如何驗(yàn)證VOLITILE 可見性保證
通過(guò)以上指令是無(wú)法驗(yàn)證的,需要查看運(yùn)行時(shí)匯編指令.

java命令

* 虛擬機(jī)參數(shù):
 * -XX:+PrintAssembly:輸出反匯編內(nèi)容冯痢;
 * -Xcomp:是讓虛擬機(jī)以編譯模式執(zhí)行代碼椎组;
 * -XX:CompileCommand=dontinline,*ClassName.methodName:讓編譯器不要內(nèi)聯(lián)methodNmae()庇勃;
 * -XX:CompileCommand=compileonly,*ClassName.methodNmae:只編譯methodNmae()责嚷;
 * 

命令示例

java -XX:+UnlockDiagnosticVMOptions -XX:+PrintAssembly -XX:CompileCommand=compileonly,*ClassName.methodName ClassFullPath

實(shí)際腳本

 java -Xcomp -XX:+UnlockDiagnosticVMOptions -XX:+PrintAssembly -XX:CompileCommand=compileonly,*VolitaleTest.main com.sparrow.jdk.volatilekey.VolitaleTest
 

部分運(yùn)行時(shí)匯編

# {method} {0x0000000019ca0290} 'main' '([Ljava/lang/String;)V' in 'com/sparrow/jdk/volatilekey/VolitaleTest'
  # parm0:    rdx:rdx   = '[Ljava/lang/String;'
  #           [sp+0x40]  (sp of caller)
  0x0000000005482360: mov     dword ptr [rsp+0ffffffffffffa000h],eax
  0x0000000005482367: push    rbp
  0x0000000005482368: sub     rsp,30h
  0x000000000548236c: mov     rsi,0d6258530h    ;   {oop(a 'java/lang/Class' = 'com/sparrow/jdk/volatilekey/VolitaleTest')}
  0x0000000005482376: mov     edi,dword ptr [rsi+68h]  ;*getstatic i
                                                ; - com.sparrow.jdk.volatilekey.VolitaleTest::main@0 (line 19)

  0x0000000005482379: inc     edi
  0x000000000548237b: mov     dword ptr [rsi+68h],edi
  0x000000000548237e: lock add dword ptr [rsp],0h  ;*putstatic i
                                                ; - com.sparrow.jdk.volatilekey.VolitaleTest::main@5 (line 19)

 0x000000000548237e: lock add dword ptr [rsp],0h  ;*putstatic i

查intel 文檔lock前綴含義枪眉,可知其保證可見性

JAVA并發(fā)編程藝術(shù)一書中,對(duì)該節(jié)有詳細(xì)描述.

本文主要介紹一些匯編概念和查看匯編的實(shí)操方法再层,關(guān)于volitile的可見性及如何保證原子性贸铜,可參考其他文章。

參考:
《深入理解JAVA虛擬機(jī)》周志明 著

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末聂受,一起剝皮案震驚了整個(gè)濱河市蒿秦,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌蛋济,老刑警劉巖棍鳖,帶你破解...
    沈念sama閱讀 218,858評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡渡处,警方通過(guò)查閱死者的電腦和手機(jī)镜悉,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)医瘫,“玉大人侣肄,你說(shuō)我怎么就攤上這事〈挤荩” “怎么了稼锅?”我有些...
    開封第一講書人閱讀 165,282評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)僚纷。 經(jīng)常有香客問我矩距,道長(zhǎng),這世上最難降的妖魔是什么怖竭? 我笑而不...
    開封第一講書人閱讀 58,842評(píng)論 1 295
  • 正文 為了忘掉前任锥债,我火速辦了婚禮,結(jié)果婚禮上痊臭,老公的妹妹穿的比我還像新娘哮肚。我一直安慰自己,他們只是感情好趣兄,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,857評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著悼嫉,像睡著了一般艇潭。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上戏蔑,一...
    開封第一講書人閱讀 51,679評(píng)論 1 305
  • 那天蹋凝,我揣著相機(jī)與錄音,去河邊找鬼总棵。 笑死鳍寂,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的情龄。 我是一名探鬼主播迄汛,決...
    沈念sama閱讀 40,406評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼骤视!你這毒婦竟也來(lái)了鞍爱?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,311評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤专酗,失蹤者是張志新(化名)和其女友劉穎睹逃,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體祷肯,經(jīng)...
    沈念sama閱讀 45,767評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡沉填,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評(píng)論 3 336
  • 正文 我和宋清朗相戀三年疗隶,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片翼闹。...
    茶點(diǎn)故事閱讀 40,090評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡斑鼻,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出橄碾,到底是詐尸還是另有隱情卵沉,我是刑警寧澤,帶...
    沈念sama閱讀 35,785評(píng)論 5 346
  • 正文 年R本政府宣布法牲,位于F島的核電站史汗,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏拒垃。R本人自食惡果不足惜停撞,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,420評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望悼瓮。 院中可真熱鬧戈毒,春花似錦、人聲如沸横堡。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,988評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)命贴。三九已至道宅,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間胸蛛,已是汗流浹背污茵。 一陣腳步聲響...
    開封第一講書人閱讀 33,101評(píng)論 1 271
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留葬项,地道東北人泞当。 一個(gè)月前我還...
    沈念sama閱讀 48,298評(píng)論 3 372
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像民珍,于是被迫代替她去往敵國(guó)和親襟士。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,033評(píng)論 2 355