JVM-01

編寫(xiě)HelloWorld.java

public class HelloWorld{
    public static void main(String[] args){
        System.out.println("HelloWorld");
    }
}

編譯:

javac HelloWorld.java

javap的使用:

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

其中-c -v -l -p -s是最常用的

-c 選項(xiàng)

$ javap -c HelloWorld.class
Compiled from "HelloWorld.java"
public class HelloWorld {
  public HelloWorld(); // ##這里默認(rèn)會(huì)添加一個(gè)構(gòu)造方法
    Code:
       0: aload_0   // 
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  public static void main(java.lang.String[]);//## main函數(shù)
    Code:
       0: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
       3: ldc           #3                  // String HelloWorld
       5: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
       8: return
}

解釋?zhuān)?/p>

  1. aload_0 這個(gè)操作碼是 aload_x 格式操作碼中的一個(gè)注暗。它們用來(lái)把**對(duì)象引用**加載到操作數(shù)棧。 x 表示正在被訪(fǎng)問(wèn)的局部變量數(shù)組的位置纲缓。在這里的 0 代表什么呢郁轻?我們知道非靜態(tài)的函數(shù)都有第一個(gè)默認(rèn)參數(shù)搁料,那就是 this熔脂,這里的 aload_0 就是把 this 入棧
  2. invokespecial #1融虽,invokespecial 指令調(diào)用實(shí)例初始化方法眉睹、私有方法荔茬、父類(lèi)方法,#1 指的是常量池中的第一個(gè)竹海,這里是方法引用java/lang/Object."<init>":()V慕蔚,也即構(gòu)造器函數(shù)
  3. return,這個(gè)操作碼屬于 ireturn斋配、lreturn孔飒、freturn、dreturn艰争、areturn 和 return 操作碼組中的一員坏瞄,其中 i 表示 int,返回整數(shù)园细,同類(lèi)的還有 l 表示 long惦积,f 表示 float,d 表示 double猛频,a 表示 對(duì)象引用狮崩。沒(méi)有前綴類(lèi)型字母的 return 表示返回 void
  4. getstatic #2,getstatic 獲取指定類(lèi)的靜態(tài)域鹿寻,并將其值壓入棧頂睦柴,#2 代表常量池中的第 2 個(gè),這里表示的是java/lang/System.out:Ljava/io/PrintStream;毡熏,其實(shí)就是java.lang.System 類(lèi)的靜態(tài)變量 out(類(lèi)型是 PrintStream)
  5. ldc #3坦敌、,ldc 用來(lái)將常量從運(yùn)行時(shí)常量池壓棧到操作數(shù)棧痢法,#3 代表常量池的第三個(gè)(字符串 Hello, World)
  6. invokevirtual #4狱窘,invokevirutal 指令調(diào)用一個(gè)對(duì)象的實(shí)例方法,#4 表示 PrintStream.println(String) 函數(shù)引用财搁,并把棧頂兩個(gè)元素出棧

-v選項(xiàng)

$ javap -v HelloWorld.class
Classfile /D:/ideaproject/jvm/HelloWorld.class
  Last modified 2019-6-19; size 411 bytes
  MD5 checksum 30c120f376b16361b854fd5c0d695ea6
  Compiled from "HelloWorld.java"
public class HelloWorld
  minor version: 0
  major version: 52
  flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
   #1 = Methodref          #6.#15         // java/lang/Object."<init>":()V
   #2 = Fieldref           #16.#17        // java/lang/System.out:Ljava/io/PrintStream;
   #3 = String             #18            // HelloWorld
   #4 = Methodref          #19.#20        // java/io/PrintStream.println:(Ljava/lang/String;)V
   #5 = Class              #18            // HelloWorld
   #6 = Class              #21            // java/lang/Object
   #7 = Utf8               <init>
   #8 = Utf8               ()V
   #9 = Utf8               Code
  #10 = Utf8               LineNumberTable
  #11 = Utf8               main
  #12 = Utf8               ([Ljava/lang/String;)V
  #13 = Utf8               SourceFile
  #14 = Utf8               HelloWorld.java
  #15 = NameAndType        #7:#8          // "<init>":()V
  #16 = Class              #22            // java/lang/System
  #17 = NameAndType        #23:#24        // out:Ljava/io/PrintStream;
  #18 = Utf8               HelloWorld
  #19 = Class              #25            // java/io/PrintStream
  #20 = NameAndType        #26:#27        // println:(Ljava/lang/String;)V
  #21 = Utf8               java/lang/Object
  #22 = Utf8               java/lang/System
  #23 = Utf8               out
  #24 = Utf8               Ljava/io/PrintStream;
  #25 = Utf8               java/io/PrintStream
  #26 = Utf8               println
  #27 = Utf8               (Ljava/lang/String;)V
{
  public HelloWorld();
    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 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 java/lang/System.out:Ljava/io/PrintStream;
         3: ldc           #3                  // String HelloWorld
         5: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
         8: return
      LineNumberTable:
        line 3: 0
        line 4: 8
}
SourceFile: "HelloWorld.java"

-l選項(xiàng)

$ javap -l HelloWorld.class
Compiled from "HelloWorld.java"
public class HelloWorld {
  public HelloWorld();
    LineNumberTable:
      line 1: 0

  public static void main(java.lang.String[]);
    LineNumberTable:
      line 3: 0
      line 4: 8
}

-s選項(xiàng):輸出簽名的類(lèi)型描述符

$ javap -s HelloWorld.class
Compiled from "HelloWorld.java"
public class HelloWorld {
  public HelloWorld();//構(gòu)造方法
    descriptor: ()V //描述: ()表示沒(méi)有參數(shù)蘸炸,V表示返回值為void

  public static void main(java.lang.String[]); //main方法
    descriptor: ([Ljava/lang/String;)V // ([Ljava/lang/String;)表示參數(shù)為數(shù)組
}

修改java代碼如下:

public class HelloWorld{

    public int test01(byte b1, short s, int a, long l2, float f1, double d, char c, boolean bool,Integer it,String str){
        return 0;
    }
}

重新編譯,查看方法簽名

$ javap -s HelloWorld.class
Compiled from "HelloWorld.java"
public class HelloWorld {
  public HelloWorld();
    descriptor: ()V

  public int test01(byte, short, int, long, float, double, char, boolean, java.lang.Integer, java.lang.String);
    descriptor: (BSIJFDCZLjava/lang/Integer;Ljava/lang/String;)I
}

查看調(diào)試信息:

編譯階段加上-g參數(shù):

$ javac -g HelloWorld.java

-l 選項(xiàng)

$ javap -l HelloWorld.class
Compiled from "HelloWorld.java"
public class HelloWorld {
  public HelloWorld();
    LineNumberTable:
      line 1: 0
    LocalVariableTable:
      Start  Length  Slot  Name   Signature
          0       5     0  this   LHelloWorld;
//this表明構(gòu)造方法默認(rèn)第一個(gè)參數(shù)是this尖奔,LHelloWorld搭儒,表示構(gòu)造方法名字和類(lèi)名一樣
  public static void main(java.lang.String[]);
    LineNumberTable:
      line 4: 0
      line 5: 8
    LocalVariableTable:
      Start  Length  Slot  Name   Signature
          0       9     0  args   [Ljava/lang/String;
//args:參數(shù)名字穷当,[Ljava/lang/String:表示參數(shù)為String數(shù)組,數(shù)組以 '[L' 開(kāi)頭
  public int test01(byte, short, int, long, float, double, char, boolean, java.lang.Integer, java.lang.String);
    LineNumberTable:
      line 8: 0
    LocalVariableTable:
      Start  Length  Slot  Name   Signature
          0       2     0  this   LHelloWorld;//this表明成員方法默認(rèn)第一個(gè)參數(shù)是this
          0       2     1    b1   B //第二個(gè)參數(shù)名字是b1淹禾, 類(lèi)型為byte馁菜,B代表byte
          0       2     2     s   S //第三個(gè)參數(shù)名字是s, 類(lèi)型為short铃岔,S代表short
          0       2     3     a   I //第四個(gè)參數(shù)名字是a汪疮, 類(lèi)型為int,I代表int
          0       2     4    l2   J //第五個(gè)參數(shù)名字是l2毁习, 類(lèi)型為long铲咨,J代表long
          0       2     6    f1   F //第六個(gè)參數(shù)名字是f1, 類(lèi)型為float蜓洪,F(xiàn)代表float
          0       2     7     d   D //第七個(gè)參數(shù)名字是d纤勒, 類(lèi)型為short,D代表double
          0       2     9     c   C //第八個(gè)參數(shù)名字是c隆檀, 類(lèi)型為char摇天,C代表char
          0       2    10  bool   Z //第九個(gè)參數(shù)名字是bool, 類(lèi)型為boolean恐仑,Z代表boolean
          0       2    11    it   Ljava/lang/Integer; //第十個(gè)參數(shù)名字是it泉坐, 類(lèi)型為Integer
                                   //引用類(lèi)型以L(fǎng)開(kāi)頭
          0       2    12   str   Ljava/lang/String; //第十一個(gè)參數(shù)名字是str, 類(lèi)型為String
}

-v 選項(xiàng)

$ javap -v HelloWorld.class
Classfile /D:/ideaproject/jvm/HelloWorld.class
  Last modified 2019-6-19; size 874 bytes
  MD5 checksum ee15f31a14c1582634907a7504bf4cf7
  Compiled from "HelloWorld.java"
public class HelloWorld
  minor version: 0
  major version: 52
  flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
   #1 = Methodref          #6.#42         // java/lang/Object."<init>":()V
   #2 = Fieldref           #43.#44        // java/lang/System.out:Ljava/io/PrintStream;
   #3 = String             #45            // helloworld
   #4 = Methodref          #46.#47        // java/io/PrintStream.println:(Ljava/lang/String;)V
   #5 = Class              #48            // HelloWorld
   #6 = Class              #49            // java/lang/Object
   #7 = Utf8               <init>
   #8 = Utf8               ()V
   #9 = Utf8               Code
  #10 = Utf8               LineNumberTable
  #11 = Utf8               LocalVariableTable
  #12 = Utf8               this
  #13 = Utf8               LHelloWorld;
  #14 = Utf8               main
  #15 = Utf8               ([Ljava/lang/String;)V
  #16 = Utf8               args
  #17 = Utf8               [Ljava/lang/String;
  #18 = Utf8               test01
  #19 = Utf8               (BSIJFDCZLjava/lang/Integer;Ljava/lang/String;)I
  #20 = Utf8               b1
  #21 = Utf8               B
  #22 = Utf8               s
  #23 = Utf8               S
  #24 = Utf8               a
  #25 = Utf8               I
  #26 = Utf8               l2
  #27 = Utf8               J
  #28 = Utf8               f1
  #29 = Utf8               F
  #30 = Utf8               d
  #31 = Utf8               D
  #32 = Utf8               c
  #33 = Utf8               C
  #34 = Utf8               bool
  #35 = Utf8               Z
  #36 = Utf8               it
  #37 = Utf8               Ljava/lang/Integer;
  #38 = Utf8               str
  #39 = Utf8               Ljava/lang/String;
  #40 = Utf8               SourceFile
  #41 = Utf8               HelloWorld.java
  #42 = NameAndType        #7:#8          // "<init>":()V
  #43 = Class              #50            // java/lang/System
  #44 = NameAndType        #51:#52        // out:Ljava/io/PrintStream;
  #45 = Utf8               helloworld
  #46 = Class              #53            // java/io/PrintStream
  #47 = NameAndType        #54:#55        // println:(Ljava/lang/String;)V
  #48 = Utf8               HelloWorld
  #49 = Utf8               java/lang/Object
  #50 = Utf8               java/lang/System
  #51 = Utf8               out
  #52 = Utf8               Ljava/io/PrintStream;
  #53 = Utf8               java/io/PrintStream
  #54 = Utf8               println
  #55 = Utf8               (Ljava/lang/String;)V
{
  public HelloWorld();
    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
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       5     0  this   LHelloWorld;

  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 java/lang/System.out:Ljava/io/PrintStream;
         3: ldc           #3                  // String helloworld
         5: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
         8: return
      LineNumberTable:
        line 4: 0
        line 5: 8
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       9     0  args   [Ljava/lang/String;

  public int test01(byte, short, int, long, float, double, char, boolean, java.lang.Integer, java.lang.String);
    descriptor: (BSIJFDCZLjava/lang/Integer;Ljava/lang/String;)I
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=13, args_size=11 //參數(shù)個(gè)數(shù)為11
         0: iconst_0
         1: ireturn
      LineNumberTable:
        line 8: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       2     0  this   LHelloWorld;
            0       2     1    b1   B
            0       2     2     s   S
            0       2     3     a   I
            0       2     4    l2   J
            0       2     6    f1   F
            0       2     7     d   D
            0       2     9     c   C
            0       2    10  bool   Z
            0       2    11    it   Ljava/lang/Integer;
            0       2    12   str   Ljava/lang/String;
}
SourceFile: "HelloWorld.java"

以16進(jìn)制查看HelloWorld.class文件:

# 將class文件轉(zhuǎn)換成16進(jìn)制
$ xxd HelloWorld.class HelloWorld.txt
$ ls
HelloWorld.class  HelloWorld.java  HelloWorld.txt
$ cat HelloWorld.txt
00000000: cafe babe 0000 0034 001c 0a00 0600 0f09  .......4........
00000010: 0010 0011 0800 120a 0013 0014 0700 1207  ................
00000020: 0015 0100 063c 696e 6974 3e01 0003 2829  .....<init>...()
00000030: 5601 0004 436f 6465 0100 0f4c 696e 654e  V...Code...LineN
00000040: 756d 6265 7254 6162 6c65 0100 046d 6169  umberTable...mai
00000050: 6e01 0016 285b 4c6a 6176 612f 6c61 6e67  n...([Ljava/lang
00000060: 2f53 7472 696e 673b 2956 0100 0a53 6f75  /String;)V...Sou
00000070: 7263 6546 696c 6501 000f 4865 6c6c 6f57  rceFile...HelloW
00000080: 6f72 6c64 2e6a 6176 610c 0007 0008 0700  orld.java.......
00000090: 160c 0017 0018 0100 0a48 656c 6c6f 576f  .........HelloWo
000000a0: 726c 6407 0019 0c00 1a00 1b01 0010 6a61  rld...........ja
000000b0: 7661 2f6c 616e 672f 4f62 6a65 6374 0100  va/lang/Object..
000000c0: 106a 6176 612f 6c61 6e67 2f53 7973 7465  .java/lang/Syste
000000d0: 6d01 0003 6f75 7401 0015 4c6a 6176 612f  m...out...Ljava/
000000e0: 696f 2f50 7269 6e74 5374 7265 616d 3b01  io/PrintStream;.
000000f0: 0013 6a61 7661 2f69 6f2f 5072 696e 7453  ..java/io/PrintS
00000100: 7472 6561 6d01 0007 7072 696e 746c 6e01  tream...println.
00000110: 0015 284c 6a61 7661 2f6c 616e 672f 5374  ..(Ljava/lang/St
00000120: 7269 6e67 3b29 5600 2100 0500 0600 0000  ring;)V.!.......
00000130: 0000 0200 0100 0700 0800 0100 0900 0000  ................
00000140: 1d00 0100 0100 0000 052a b700 01b1 0000  .........*......
00000150: 0001 000a 0000 0006 0001 0000 0001 0009  ................
00000160: 000b 000c 0001 0009 0000 0025 0002 0001  ...........%....
00000170: 0000 0009 b200 0212 03b6 0004 b100 0000  ................
00000180: 0100 0a00 0000 0a00 0200 0000 0300 0800  ................
00000190: 0400 0100 0d00 0000 0200 0e              ...........

class文件各個(gè)部分的解釋

  1. 魔數(shù)

    cafe babe

    class 的魔數(shù)為 0xCAFEBABE, 這個(gè)魔數(shù)是 JVM 識(shí)別 .class 文件的標(biāo)志裳仆,虛擬機(jī)在加載類(lèi)文件之前會(huì)先檢查這四個(gè)字節(jié)腕让,如果不是 0xCAFEBABE 則拒絕加載該文件

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市歧斟,隨后出現(xiàn)的幾起案子纯丸,更是在濱河造成了極大的恐慌,老刑警劉巖静袖,帶你破解...
    沈念sama閱讀 210,978評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件觉鼻,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡队橙,警方通過(guò)查閱死者的電腦和手機(jī)坠陈,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,954評(píng)論 2 384
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)捐康,“玉大人仇矾,你說(shuō)我怎么就攤上這事〗庾埽” “怎么了贮匕?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,623評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵,是天一觀(guān)的道長(zhǎng)倾鲫。 經(jīng)常有香客問(wèn)我粗合,道長(zhǎng),這世上最難降的妖魔是什么乌昔? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,324評(píng)論 1 282
  • 正文 為了忘掉前任隙疚,我火速辦了婚禮,結(jié)果婚禮上磕道,老公的妹妹穿的比我還像新娘供屉。我一直安慰自己,他們只是感情好溺蕉,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,390評(píng)論 5 384
  • 文/花漫 我一把揭開(kāi)白布伶丐。 她就那樣靜靜地躺著,像睡著了一般疯特。 火紅的嫁衣襯著肌膚如雪哗魂。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,741評(píng)論 1 289
  • 那天漓雅,我揣著相機(jī)與錄音录别,去河邊找鬼。 笑死邻吞,一個(gè)胖子當(dāng)著我的面吹牛组题,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播抱冷,決...
    沈念sama閱讀 38,892評(píng)論 3 405
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼崔列,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了旺遮?” 一聲冷哼從身側(cè)響起赵讯,我...
    開(kāi)封第一講書(shū)人閱讀 37,655評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎耿眉,沒(méi)想到半個(gè)月后瘦癌,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,104評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡跷敬,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,451評(píng)論 2 325
  • 正文 我和宋清朗相戀三年讯私,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片西傀。...
    茶點(diǎn)故事閱讀 38,569評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡斤寇,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出拥褂,到底是詐尸還是另有隱情娘锁,我是刑警寧澤,帶...
    沈念sama閱讀 34,254評(píng)論 4 328
  • 正文 年R本政府宣布饺鹃,位于F島的核電站莫秆,受9級(jí)特大地震影響间雀,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜镊屎,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,834評(píng)論 3 312
  • 文/蒙蒙 一惹挟、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧缝驳,春花似錦连锯、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,725評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至夏伊,卻和暖如春摇展,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背溺忧。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,950評(píng)論 1 264
  • 我被黑心中介騙來(lái)泰國(guó)打工吗购, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人砸狞。 一個(gè)月前我還...
    沈念sama閱讀 46,260評(píng)論 2 360
  • 正文 我出身青樓捻勉,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親刀森。 傳聞我的和親對(duì)象是個(gè)殘疾皇子踱启,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,446評(píng)論 2 348

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