如何查看字節(jié)碼

  1. 把java文件編譯生成class文件,
// 編寫HelloByteCode.java
public class HelloByteCode {
    public static void main(String[] args) {
        HelloByteCode obj = new HelloByteCode();
    }
}
  1. 通過命令行生成class文件
    通過Android Studio idea 查看生成的class文件,由此也可以看出,默認(rèn)構(gòu)造函數(shù)就在這里生成了
// HelloByteCode.class
public class HelloByteCode {
    public HelloByteCode() {
    }

    public static void main(String[] var0) {
        new HelloByteCode();
    }
}

其中javac有很多參數(shù)可用,可以通過javac --help查看

javac --help
用法: javac <options> <source files>
其中, 可能的選項(xiàng)包括:
  @<filename>                  從文件讀取選項(xiàng)和文件名
  -Akey[=value]                傳遞給注釋處理程序的選項(xiàng)
  --add-modules <模塊>(,<模塊>)*
        除了初始模塊之外要解析的根模塊; 如果 <module>
                為 ALL-MODULE-PATH, 則為模塊路徑中的所有模塊。
  --boot-class-path <path>, -bootclasspath <path>
        覆蓋引導(dǎo)類文件的位置
  --class-path <path>, -classpath <path>, -cp <path>
        指定查找用戶類文件和注釋處理程序的位置
  -d <directory>               指定放置生成的類文件的位置
  -deprecation                 輸出使用已過時(shí)的 API 的源位置
  --enable-preview             啟用預(yù)覽語言功能。要與 -source 或 --release 一起使用。
  -encoding <encoding>         指定源文件使用的字符編碼
  -endorseddirs <dirs>         覆蓋簽名的標(biāo)準(zhǔn)路徑的位置
  -extdirs <dirs>              覆蓋所安裝擴(kuò)展的位置
  -g                           生成所有調(diào)試信息
  -g:{lines,vars,source}       只生成某些調(diào)試信息
  -g:none                      不生成任何調(diào)試信息
  -h <directory>               指定放置生成的本機(jī)標(biāo)頭文件的位置
  --help, -help, -?            輸出此幫助消息
  --help-extra, -X             輸出額外選項(xiàng)的幫助
  -implicit:{none,class}       指定是否為隱式引用文件生成類文件
  -J<flag>                     直接將 <標(biāo)記> 傳遞給運(yùn)行時(shí)系統(tǒng)
  --limit-modules <模塊>(,<模塊>)*
        限制可觀察模塊的領(lǐng)域
  --module <模塊>(,<模塊>)*, -m <模塊>(,<模塊>)*
        只編譯指定的模塊,請(qǐng)檢查時(shí)間戳
  --module-path <path>, -p <path>
        指定查找應(yīng)用程序模塊的位置
  --module-source-path <module-source-path>
        指定查找多個(gè)模塊的輸入源文件的位置
  --module-version <版本>        指定正在編譯的模塊版本
  -nowarn                      不生成任何警告
  -parameters                  生成元數(shù)據(jù)以用于方法參數(shù)的反射
  -proc:{none,only}            控制是否執(zhí)行注釋處理和/或編譯。
  -processor <class1>[,<class2>,<class3>...]
        要運(yùn)行的注釋處理程序的名稱; 繞過默認(rèn)的搜索進(jìn)程
  --processor-module-path <path>
        指定查找注釋處理程序的模塊路徑
  --processor-path <path>, -processorpath <path>
        指定查找注釋處理程序的位置
  -profile <profile>           請(qǐng)確保使用的 API 在指定的配置文件中可用
  --release <release>          針對(duì)特定發(fā)行版進(jìn)行編譯。支持的發(fā)行版:7, 8, 9, 10, 11, 12
  -s <directory>               指定放置生成的源文件的位置
  --source <release>, -source <release>
        提供與指定發(fā)行版的源兼容性。支持的發(fā)行版:7, 8, 9, 10, 11, 12
  --source-path <path>, -sourcepath <path>
        指定查找輸入源文件的位置
  --system <jdk>|none          覆蓋系統(tǒng)模塊位置
  --target <release>, -target <release>
        生成針對(duì)特定 VM 版本的類文件。支持的版本:7, 8, 9, 10, 11, 12
  --upgrade-module-path <path>
        覆蓋可升級(jí)模塊位置
  -verbose                     輸出有關(guān)編譯器正在執(zhí)行的操作的消息
  --version, -version          版本信息
  -Werror                      出現(xiàn)警告時(shí)終止編譯

其中javac -g HelloByteCode.java 可以生成測試信息,大家可以自行嘗試

  1. 查看字節(jié)碼
    通過命令行方式
javap -c -verbose HelloByteCode.class
javap -c -verbose HelloByteCode.class
Classfile /Users/xxxDesktop/java/HelloByteCode.class
  Last modified 2022年9月29日; size 288 bytes
  MD5 checksum b572cf2c2ccd067ad41d5c137a875273
  Compiled from "HelloByteCode.java"
public class HelloByteCode
  minor version: 0
  major version: 56
  flags: (0x0021) ACC_PUBLIC, ACC_SUPER
  this_class: #2                          // HelloByteCode
  super_class: #4                         // java/lang/Object
  interfaces: 0, fields: 0, methods: 2, attributes: 1
Constant pool:
   #1 = Methodref          #4.#13         // java/lang/Object."<init>":()V
   #2 = Class              #14            // HelloByteCode
   #3 = Methodref          #2.#13         // HelloByteCode."<init>":()V
   #4 = Class              #15            // java/lang/Object
   #5 = Utf8               <init>
   #6 = Utf8               ()V
   #7 = Utf8               Code
   #8 = Utf8               LineNumberTable
   #9 = Utf8               main
  #10 = Utf8               ([Ljava/lang/String;)V
  #11 = Utf8               SourceFile
  #12 = Utf8               HelloByteCode.java
  #13 = NameAndType        #5:#6          // "<init>":()V
  #14 = Utf8               HelloByteCode
  #15 = Utf8               java/lang/Object
{
  public HelloByteCode();
    descriptor: ()V
    flags: (0x0001) 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: (0x0009) ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=2, args_size=1
         0: new           #2                  // class HelloByteCode
         3: dup
         4: invokespecial #3                  // Method "<init>":()V
         7: astore_1
         8: return
      LineNumberTable:
        line 3: 0
        line 4: 8
}

如果是帶-g測試信息的class文件,效果是如下,多了額外的本地變量信息

 javap -c -verbose HelloByteCode.class
Classfile /Users/hzhenx/Desktop/java/HelloByteCode.class
  Last modified 2022年9月29日; size 415 bytes
  MD5 checksum 05c705e182f58d3b5aa49c28d9e70d1d
  Compiled from "HelloByteCode.java"
public class HelloByteCode
  minor version: 0
  major version: 56
  flags: (0x0021) ACC_PUBLIC, ACC_SUPER
  this_class: #2                          // HelloByteCode
  super_class: #4                         // java/lang/Object
  interfaces: 0, fields: 0, methods: 2, attributes: 1
Constant pool:
   #1 = Methodref          #4.#19         // java/lang/Object."<init>":()V
   #2 = Class              #20            // HelloByteCode
   #3 = Methodref          #2.#19         // HelloByteCode."<init>":()V
   #4 = Class              #21            // java/lang/Object
   #5 = Utf8               <init>
   #6 = Utf8               ()V
   #7 = Utf8               Code
   #8 = Utf8               LineNumberTable
   #9 = Utf8               LocalVariableTable
  #10 = Utf8               this
  #11 = Utf8               LHelloByteCode;
  #12 = Utf8               main
  #13 = Utf8               ([Ljava/lang/String;)V
  #14 = Utf8               args
  #15 = Utf8               [Ljava/lang/String;
  #16 = Utf8               obj
  #17 = Utf8               SourceFile
  #18 = Utf8               HelloByteCode.java
  #19 = NameAndType        #5:#6          // "<init>":()V
  #20 = Utf8               HelloByteCode
  #21 = Utf8               java/lang/Object
{
  public HelloByteCode();
    descriptor: ()V
    flags: (0x0001) 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   LHelloByteCode;

  public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=2, args_size=1
         0: new           #2                  // class HelloByteCode
         3: dup
         4: invokespecial #3                  // Method "<init>":()V
         7: astore_1
         8: return
      LineNumberTable:
        line 3: 0
        line 4: 8
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       9     0  args   [Ljava/lang/String;
            8       1     1   obj   LHelloByteCode;
}
SourceFile: "HelloByteCode.java"

其中可以看到多了

 LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       9     0  args   [Ljava/lang/String;
            8       1     1   obj   LHelloByteCode;

也可以通過Android Studio 的插件jclasslib可視化去查看

  1. Android Stuido 安裝插件


    1. 打開Preferences

    進(jìn)入Plugins,搜索jclasslib

    然后點(diǎn)擊安裝,重啟ide

  2. 使用jclasslib查看字節(jié)碼


    IDE打開class文件

    View->Show bytecode
各種信息直觀展示

至于怎么讀懂字節(jié)碼后面更新

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容