java經常使用工具——javap

javap是jdk自帶的一個工具,能夠對代碼反編譯,也能夠查看java編譯器生成的字節碼。java

通常狀況下,不多有人使用javap對class文件進行反編譯,由於有不少成熟的反編譯工具可使用,好比jad。可是,javap還能夠查看java編譯器爲咱們生成的字節碼。經過它,能夠對照源代碼和字節碼,從而瞭解不少編譯器內部的工做。app

實例

javap命令分解一個class文件,它根據options來決定到底輸出什麼。若是沒有使用options,那麼javap將會輸出包,類裏的protected和public域以及類裏的全部方法。javap將會把它們輸出在標準輸出上。來看這個例子,先編譯(javac)下面這個類。工具

import java.awt.*;
import java.applet.*;

public class DocFooter extends Applet {
        String date;
        String email;

        public void init() {
                resize(500,100);
                date = getParameter("LAST_UPDATED");
                email = getParameter("EMAIL");
        }

        public void paint(Graphics g) {
                g.drawString(date + " by ",100, 15);
                g.drawString(email,290,15);
        }
}

在命令行上鍵入javap DocFooter後,輸出結果以下ui

Compiled from "DocFooter.java"
public class DocFooter extends java.applet.Applet {
  java.lang.String date;
  java.lang.String email;
  public DocFooter();
  public void init();
  public void paint(java.awt.Graphics);
}

若是加入了-c,即javap -c DocFooter,那麼輸出結果以下spa

Compiled from "DocFooter.java"
public class DocFooter extends java.applet.Applet {
  java.lang.String date;

  java.lang.String email;

  public DocFooter();
    Code:
       0: aload_0       
       1: invokespecial #1                  // Method java/applet/Applet."<init>":()V
       4: return        

  public void init();
    Code:
       0: aload_0       
       1: sipush        500
       4: bipush        100
       6: invokevirtual #2                  // Method resize:(II)V
       9: aload_0       
      10: aload_0       
      11: ldc           #3                  // String LAST_UPDATED
      13: invokevirtual #4                  // Method getParameter:(Ljava/lang/String;)Ljava/lang/String;
      16: putfield      #5                  // Field date:Ljava/lang/String;
      19: aload_0       
      20: aload_0       
      21: ldc           #6                  // String EMAIL
      23: invokevirtual #4                  // Method getParameter:(Ljava/lang/String;)Ljava/lang/String;
      26: putfield      #7                  // Field email:Ljava/lang/String;
      29: return        

  public void paint(java.awt.Graphics);
    Code:
       0: aload_1       
       1: new           #8                  // class java/lang/StringBuilder
       4: dup           
       5: invokespecial #9                  // Method java/lang/StringBuilder."<init>":()V
       8: aload_0       
       9: getfield      #5                  // Field date:Ljava/lang/String;
      12: invokevirtual #10                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      15: ldc           #11                 // String  by 
      17: invokevirtual #10                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      20: invokevirtual #12                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      23: bipush        100
      25: bipush        15
      27: invokevirtual #13                 // Method java/awt/Graphics.drawString:(Ljava/lang/String;II)V
      30: aload_1       
      31: aload_0       
      32: getfield      #7                  // Field email:Ljava/lang/String;
      35: sipush        290
      38: bipush        15
      40: invokevirtual #13                 // Method java/awt/Graphics.drawString:(Ljava/lang/String;II)V
      43: return        
}

上面輸出的內容就是字節碼。命令行

用法摘要

-help 幫助
-l 輸出行和變量的表
-public 只輸出public方法和域
-protected 只輸出public和protected類和成員
-package 只輸出包,public和protected類和成員,這是默認的
-p -private 輸出全部類和成員
-s 輸出內部類型簽名
-c 輸出分解後的代碼,例如,類中每個方法內,包含java字節碼的指令,
-verbose 輸出棧大小,方法參數的個數
-constants 輸出靜態final常量

總結

javap能夠用於反編譯和查看編譯器編譯後的字節碼。平時通常用javap -c比較多,該命令用於列出每一個方法所執行的JVM指令,並顯示每一個方法的字節碼的實際做用。能夠經過字節碼和源代碼的對比,深刻分析java的編譯原理,瞭解和解決各類Java原理級別的問題。code

相關文章
相關標籤/搜索