說說javap命令

来源:http://www.cnblogs.com/frinder6/archive/2016/04/27/5440173.html
-Advertisement-
Play Games

javap定義 測試類 javap命令參數 javap -version javap -p javap -public javap -protected javap -l javap -package javap -v/-p -v javap -c 文章開頭的demo中最終的結果是什麼呢? 這個地方 ...


javap定義

javap是 Java class文件分解器,可以反編譯(即對javac編譯的文件進行反編譯),也可以查看java編譯器生成的位元組碼。用於分解class文件。

測試類

public class JavapTest {

    private static final int _P_1 = 1;
    public static final int _P_2 = 2;

    public static void main(String[] args) {
        int m = 0, n = 0;
        for (int i = 0; i < 10; i++) {
            m = m++;
            n = ++n;
        }
        System.out.println("m = " + m);
        System.out.println("n = " + n);
    }
}

javap命令參數

C:\>javap -help
用法: javap <options> <classes>
其中, 可能的選項包括:
  -help  --help  -?        輸出此用法消息
  -version                 版本信息
  -v  -verbose             輸出附加信息
  -l                       輸出行號和本地變數表
  -public                  僅顯示公共類和成員
  -protected               顯示受保護的/公共類和成員
  -package                 顯示程式包/受保護的/公共類
                           和成員 (預設)
  -p  -private             顯示所有類和成員
  -c                       對代碼進行反彙編
  -s                       輸出內部類型簽名
  -sysinfo                 顯示正在處理的類的
                           系統信息 (路徑, 大小, 日期, MD5 散列)
  -constants               顯示靜態最終常量
  -classpath <path>        指定查找用戶類文件的位置
  -bootclasspath <path>    覆蓋引導類文件的位置

javap -version

C:\>javap -version
1.7.0_71

顯示java版本

javap -p

C:\Users\user\Desktop>javap -p JavapTest.class
Compiled from "JavapTest.java"
public class com.method.handler.JavapTest {
  private static final int _P_1;
  public static final int _P_2;
  public com.method.handler.JavapTest();
  public static void main(java.lang.String[]);
  private void say();
}

顯示類所有可訪問修飾符範圍》private的成員

javap -public

C:\Users\user\Desktop>javap -public JavapTest.class
Compiled from "JavapTest.java"
public class com.method.handler.JavapTest {
  public static final int _P_2;
  public com.method.handler.JavapTest();
  public static void main(java.lang.String[]);
}

顯示類的public成員

javap -protected

C:\Users\user\Desktop>javap -protected JavapTest.class
Compiled from "JavapTest.java"
public class com.method.handler.JavapTest {
  public static final int _P_2;
  public com.method.handler.JavapTest();
  public static void main(java.lang.String[]);
}

顯示類所有可訪問修飾符範圍》protected的成員

javap -l

C:\Users\user\Desktop>javap -p -l JavapTest.class
Compiled from "JavapTest.java"
public class com.method.handler.JavapTest {
  private static final int _P_1;

  public static final int _P_2;

  public com.method.handler.JavapTest();
    LineNumberTable:
      line 6: 0

  public static void main(java.lang.String[]);
    LineNumberTable:
      line 12: 0
      line 13: 4
      line 14: 12
      line 15: 17
      line 13: 22
      line 17: 28
      line 18: 53
      line 19: 78

  private void say();
    LineNumberTable:
      line 23: 0
      line 24: 8
}

輸出行號和本地變數表?看的不是很明白

javap -package

C:\Users\user\Desktop>javap -package JavapTest.class
Compiled from "JavapTest.java"
public class com.method.handler.JavapTest {
  public static final int _P_2;
  public com.method.handler.JavapTest();
  public static void main(java.lang.String[]);
}

與javap -public作用類似

javap -v/-p -v

C:\Users\user\Desktop>javap -p -v JavapTest.class
Classfile /C:/Users/frinder_liu/Desktop/JavapTest.class
  Last modified 2016-4-27; size 911 bytes
  MD5 checksum e903be7495f5c462d6459a792e063628
  Compiled from "JavapTest.java"
public class com.method.handler.JavapTest
  SourceFile: "JavapTest.java"
  minor version: 0
  major version: 51
  flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
   #1 = Methodref          #13.#30        //  java/lang/Object."<init>":()V
   #2 = Fieldref           #31.#32        //  java/lang/System.out:Ljava/io/PrintStream;
   #3 = Class              #33            //  java/lang/StringBuilder
   #4 = Methodref          #3.#30         //  java/lang/StringBuilder."<init>":()V
   #5 = String             #34            //  m =
   #6 = Methodref          #3.#35         //  java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilde
r;
   #7 = Methodref          #3.#36         //  java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
   #8 = Methodref          #3.#37         //  java/lang/StringBuilder.toString:()Ljava/lang/String;
   #9 = Methodref          #38.#39        //  java/io/PrintStream.println:(Ljava/lang/String;)V
  #10 = String             #40            //  n =
  #11 = String             #41            //  hello world...
  #12 = Class              #42            //  com/method/handler/JavapTest
  #13 = Class              #43            //  java/lang/Object
  #14 = Utf8               _P_1
  #15 = Utf8               I
  #16 = Utf8               ConstantValue
  #17 = Integer            1
  #18 = Utf8               _P_2
  #19 = Integer            2
  #20 = Utf8               <init>
  #21 = Utf8               ()V
  #22 = Utf8               Code
  #23 = Utf8               LineNumberTable
  #24 = Utf8               main
  #25 = Utf8               ([Ljava/lang/String;)V
  #26 = Utf8               StackMapTable
  #27 = Utf8               say
  #28 = Utf8               SourceFile
  #29 = Utf8               JavapTest.java
  #30 = NameAndType        #20:#21        //  "<init>":()V
  #31 = Class              #44            //  java/lang/System
  #32 = NameAndType        #45:#46        //  out:Ljava/io/PrintStream;
  #33 = Utf8               java/lang/StringBuilder
  #34 = Utf8               m =
  #35 = NameAndType        #47:#48        //  append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
  #36 = NameAndType        #47:#49        //  append:(I)Ljava/lang/StringBuilder;
  #37 = NameAndType        #50:#51        //  toString:()Ljava/lang/String;
  #38 = Class              #52            //  java/io/PrintStream
  #39 = NameAndType        #53:#54        //  println:(Ljava/lang/String;)V
  #40 = Utf8               n =
  #41 = Utf8               hello world...
  #42 = Utf8               com/method/handler/JavapTest
  #43 = Utf8               java/lang/Object
  #44 = Utf8               java/lang/System
  #45 = Utf8               out
  #46 = Utf8               Ljava/io/PrintStream;
  #47 = Utf8               append
  #48 = Utf8               (Ljava/lang/String;)Ljava/lang/StringBuilder;
  #49 = Utf8               (I)Ljava/lang/StringBuilder;
  #50 = Utf8               toString
  #51 = Utf8               ()Ljava/lang/String;
  #52 = Utf8               java/io/PrintStream
  #53 = Utf8               println
  #54 = Utf8               (Ljava/lang/String;)V
{
  private static final int _P_1;
    flags: ACC_PRIVATE, ACC_STATIC, ACC_FINAL
    ConstantValue: int 1

  public static final int _P_2;
    flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL
    ConstantValue: int 2

  public com.method.handler.JavapTest();
    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 6: 0

  public static void main(java.lang.String[]);
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=3, locals=4, args_size=1
         0: iconst_0
         1: istore_1
         2: iconst_0
         3: istore_2
         4: iconst_0
         5: istore_3
         6: iload_3
         7: bipush        10
         9: if_icmpge     28
        12: iload_1
        13: iinc          1, 1
        16: istore_1
        17: iinc          2, 1
        20: iload_2
        21: istore_2
        22: iinc          3, 1
        25: goto          6
        28: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
        31: new           #3                  // class java/lang/StringBuilder
        34: dup
        35: invokespecial #4                  // Method java/lang/StringBuilder."<init>":()V
        38: ldc           #5                  // String m =
        40: invokevirtual #6                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/St
ringBuilder;
        43: iload_1
        44: invokevirtual #7                  // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
        47: invokevirtual #8                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
        50: invokevirtual #9                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
        53: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
        56: new           #3                  // class java/lang/StringBuilder
        59: dup
        60: invokespecial #4                  // Method java/lang/StringBuilder."<init>":()V
        63: ldc           #10                 // String n =
        65: invokevirtual #6                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/St
ringBuilder;
        68: iload_2
        69: invokevirtual #7                  // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
        72: invokevirtual #8                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
        75: invokevirtual #9                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
        78: return
      LineNumberTable:
        line 12: 0
        line 13: 4
        line 14: 12
        line 15: 17
        line 13: 22
        line 17: 28
        line 18: 53
        line 19: 78
      StackMapTable: number_of_entries = 2
           frame_type = 254 /* append */
             offset_delta = 6
        locals = [ int, int, int ]
           frame_type = 250 /* chop */
          offset_delta = 21


  private void say();
    flags: ACC_PRIVATE
    Code:
      stack=2, locals=1, args_size=1
         0: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
         3: ldc           #11                 // String hello world...
         5: invokevirtual #9                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
         8: return
      LineNumberTable:
        line 23: 0
        line 24: 8
}

命令說明是:輸出附加信息
class文件的路徑、最後修改時間、文件大小等
類的全路徑、源(java)文件等
常量池
常量定義、值
構造方法
程式調用及執行邏輯(這個涉及的內容就比較多了)

總之,javap -v命令是很強大的一個命令!

javap -c

C:\Users\user\Desktop>javap -c JavapTest.class
Compiled from "JavapTest.java"
public class com.method.handler.JavapTest {
  public static final int _P_2;

  public com.method.handler.JavapTest();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  public static void main(java.lang.String[]);
    Code:
       0: iconst_0
       1: istore_1
       2: iconst_0
       3: istore_2
       4: iconst_0
       5: istore_3
       6: iload_3
       7: bipush        10
       9: if_icmpge     28
      12: iload_1
      13: iinc          1, 1
      16: istore_1
      17: iinc          2, 1
      20: iload_2
      21: istore_2
      22: iinc          3, 1
      25: goto          6
      28: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
      31: new           #3                  // class java/lang/StringBuilder
      34: dup
      35: invokespecial #4                  // Method java/lang/StringBuilder."<init>":()V
      38: ldc           #5                  // String m =
      40: invokevirtual #6                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/Stri
ngBuilder;
      43: iload_1
      44: invokevirtual #7                  // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
      47: invokevirtual #8                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      50: invokevirtual #9                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      53: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
      56: new           #3                  // class java/lang/StringBuilder
      59: dup
      60: invokespecial #4                  // Method java/lang/StringBuilder."<init>":()V
      63: ldc           #10                 // String n =
      65: invokevirtual #6                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/Stri
ngBuilder;
      68: iload_2
      69: invokevirtual #7                  // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
      72: invokevirtual #8                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      75: invokevirtual #9                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      78: return
}

其實,javap -c 輸出內部javap -v中已經有了,我們詳細介紹下javap -c命令的輸出內容
0: iconst_0 前面0:表示執行的順序,iconst_0把值 0 放入棧頂,_0中的0代表壓棧的值,如:iconst_5,即把5壓入棧頂
1: istore_1 將棧頂的值放入變數1 中,_1代表變數的序列,本例中為:m,如:istore_2即為變數n賦值
6: iload_3 將變數3 即 i 的的值放入棧頂,與iconst不同的是,iload操作的值是已經定義好存在的值,iconst是定義時的壓棧操作
13: iinc 1, 1 將變數1 的值加1

文章開頭的demo中最終的結果是什麼呢?

m = 0
n = 10

為什麼呢?
我們來關註下這幾行:
12: iload_1             -- 將變數1 值放入棧項
13: iinc          1, 1  -- 將變數1 增加1 變為2,棧頂值仍然是1。其中第一個1 表示變數,第二個1 表示增量
16: istore_1            -- 將棧頂值賦值給變數1,變數1 仍然為1
17: iinc          2, 1  -- 將變數2 增加1 變為2,棧頂值仍然是1。其中第一個2 表示變數,第二個1 表示增量
20: iload_2             -- 將變數2 值放入棧頂
21: istore_2            -- 將棧頂值賦值給變數2,變數2 值為2


記住一個點:
int m = 0, n = 0;
m = m++;  -- 會先將m值(即0)賦值給m後再++
n = ++n;  -- n先++後再把值賦值給n
此時,m = 0, n = 1;

這個地方有點繞,需要多看幾次,理順邏輯與關係!

這裡可以參考下http://blog.csdn.net/junsure2012/article/details/7099222,講的很詳細也易懂!

 

javap -s/-p -s

C:\Users\user\Desktop>javap -p -s JavapTest.class
Compiled from "JavapTest.java"
public class com.method.handler.JavapTest {
  private static final int _P_1;
    Signature: I
  public static final int _P_2;
    Signature: I
  public com.method.handler.JavapTest();
    Signature: ()V

  public static void main(java.lang.String[]);
    Signature: ([Ljava/lang/String;)V

  private void say();
    Signature: ()V
}

輸出內部類型簽名

javap -sysinfo/-p -sysinfo

C:\Users\user\Desktop>javap -sysinfo JavapTest.class
Classfile /C:/Users/user/Desktop/JavapTest.class
  Last modified 2016-4-27; size 911 bytes
  MD5 checksum 3f6dfcf7121785760b234224c5d135fd
  Compiled from "JavapTest.java"
public class com.method.handler.JavapTest {
  public static final int _P_2;
  public com.method.handler.JavapTest();
  public static void main(java.lang.String[]);
}

顯示正在處理的類的
系統信息 (路徑, 大小, 日期, MD5 散列)

javap -constants/-p -constants

C:\Users\user\Desktop>javap -constants JavapTest.class
Compiled from "JavapTest.java"
public class com.method.handler.JavapTest {
  public static final int _P_2 = 2;
  public com.method.handler.JavapTest();
  public static void main(java.lang.String[]);
}

顯示靜態最終常量

javap -classpath/-bootclasspath

先跳過

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • <MySQL資料庫操作> 1.創建資料庫. 在MySQL中應用 create database 語句創建資料庫.格式如下: create database db_name; db_name 為資料庫名,必須為合法名稱.規定如下: a.不能與其他資料庫重名. b.名字可以是任意的字母,阿拉伯數字,下劃 ...
  • 變數的可見性(即作用域)和生命期既有區別,又有聯繫。 一個變數在程式的某處沒有可見性,但生命期任然可以存在,比如局部靜態變數的可見性在它所在的函數裡面,在函數外部不可訪問,但是它的生命期確是整個程式的運行期間;而一個變數生命期結束,它也就沒有了可見性,就像局部變數,隨著棧空間的釋放,它也就不存在了, ...
  • WebView提供了在Android應用中展示網頁的強大功能。也是目前Hybird app的大力發展的基礎。作為Android系統的一個非常重要的組件,它提供兩方面的強大的能力:對HTML的解析,佈局和繪製;對JavaScript的解釋和執行。Hybird App的組成是Native+H5,Nati ...
  • 在如今併發的環境下,對大數據量的查詢採用緩存是最好不過的了,本文使用redis搭建集群 (個人喜歡redis,對memcache不感冒) redis是3.0後增加的集群功能,非常強大 集群中應該至少有三個節點,每個節點有一備份節點。這樣算下來至少需要6台伺服器 考慮到有些朋友的電腦配置不是很高,跑多 ...
  • 運行結果: Hello JAVA Hello JAVA true b Hello JAVA false false false false 當創建String類型的變數並賦值時,會先到常量池中尋找是否存在這個常量的字元串,如果有則將引用(即地址)返回,如果沒有則在常量池中開闢空間並賦值沒這個給定的常 ...
  • from json_response import JsonResponse, json_response as json_resp 使用的語句如上,其實並不是沒有安裝,只是需要升級一下 pip install django-json-response --upgrade ...
  • 註:文章原文為Dr. Charles Severance 的 《Python for Informatics》。文中代碼用3.4版改寫,併在本機測試通過。 12.9 辭彙表 BeautifulSoup: 一個用於分析HTML文檔,並從中抓取數據的Python庫。它彌補了大部分在瀏覽器中被忽略的HTM ...
  • HashSet and HashMap "本文github地址" 總體介紹 之所以把 HashSet 和 HashMap 放在一起講解,是因為二者在Java里有著相同的實現,前者僅僅是對後者做了一層包裝,也就是說 HashSet 裡面有一個 HashMap (適配器模式) 。因此本文將重點分析 Ha ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...