`

Java编译之常用命令 -javap

阅读更多
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
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

先跳过
分享到:
评论

相关推荐

    windows命令行中java和javac、javap使用详解(java编译命令)

    3. javap命令的用法:javap命令用于反编译.class文件,显示Java类文件的内部结构,包括方法、变量等信息。它可以帮助开发者理解Java编译器在编译过程中对类文件的处理方式。常用选项包括-c(显示方法的具体字节码)...

    java 2语言命令详解

    - `javac`命令用于将源代码(.java文件)编译成字节码(.class文件)。例如,`javac HelloWorld.java`将编译名为HelloWorld.java的源文件。 - 编译选项包括:-g(添加调试信息)、-d(指定目标目录)、-cp或-...

    21天学通JAVA_入门精品

    4. JDK常用命令: - javac命令用于编译Java源文件,生成字节码文件。其中,-g 参数用于生成调试信息,-O 参数用于优化字节码,-classpath 用于指定类路径,-d 用于指定输出目录等。 - native2ascii 用于处理...

    jdk常用命令

    本文将深入探讨JDK中的常用命令,这些命令对于任何Java开发者来说都是必不可少的知识点。通过理解并熟练运用这些命令,可以极大地提高开发效率。 1. **javac**:这是Java编译器,用于将源代码(.java文件)转换成可...

    Java电子教案(PPT)-第1章-Java简介(ppt文档).ppt

    4. **JDK常用命令**: - **javac**:Java编译器,用于将源代码编译成字节码。常见的选项如-g用于控制调试信息的生成,-classpath指定类路径等。 - **java**:Java解释器,用于运行已编译的Java程序。 - **其他...

    21天学通JAVA(高清版).pdf

    #### 四、JDK常用命令详解 - **编译器命令**: - **`javac`**:用于编译Java源代码。 - `-g`: 生成调试信息。 - `-g:none`: 不生成调试信息。 - `-g:{lines,vars,source}`: 只生成部分调试信息。 - `-O`: 优化...

    21天学通JAVA高清版(护眼绿豆沙底色版)

    5. JDK常用命令 - javac:编译Java源代码。支持各种参数,如生成调试信息、优化类文件、指定编码等。 - native2ascii:用于编码转换,将Unicode编码的中文转换为ASCII编码,或反之。 - javap:反编译class文件,...

    java命令详解 高手进阶

    - **常用命令**: - `run`:运行程序。 - `stop`:停止程序。 - `step`:单步执行。 - `continue`:继续执行。 - `print`:打印变量值。 - `set`:设置断点。 - `clear`:清除断点。 - `list`:列出源代码。...

    javap命令的使用技巧

    javap 命令是 JDK 自带的一个工具,它可以对代码反编译,也可以查看 Java 编译器生成的字节码,对代码的执行过程进行分析,了解 JVM 内部的工作。javap 命令可以将 class 文件反编译成易于阅读的格式,展示类的结构...

    Java2语言命令详解

    以下是对Java2语言中常用命令的详细解析: 1. **javac**:Java编译器 `javac`命令用于将源代码文件(.java)编译成字节码文件(.class)。例如: ``` javac HelloWorld.java ``` 这个命令会将`HelloWorld.java...

    java 2语言命令详解 JAVA程序设计

    Java 2语言命令详解是Java编程领域中的一个重要环节,它涉及到如何在命令行环境中编译、运行和管理Java应用程序。本文将深入解析Java 2语言的相关命令,帮助读者理解和掌握JAVA程序设计的基础知识。 首先,我们需要...

    Java代码编译和反编译的那些事儿

    常用的Java反编译工具有javap、jad和cfr。javap是jdk自带的一个工具,可以对代码反编译,也可以查看java编译器生成的字节码。jad和cfr都是流行的Java反编译工具,它们可以将class文件转换成java文件。 六、反编译的...

    JAVA命令大全(bin目录下命令描述)

    在Java开发中,JDK的bin目录下包含了许多用于编译、运行、调试和分析Java程序的命令工具。以下是几个最重要的命令及其详细解释: 1. **java.exe**: 这是运行Java应用程序的命令,当你输入`java MainClass`,它会...

    JDK常用命令.pdf

    掌握JDK的常用命令对于Java开发者来说非常重要,因为这些命令是实现Java程序编写、编译、调试、文档化、打包和部署的基本手段。 首先,我们需要了解JDK的安装目录。通常,我们会设置JAVA_HOME环境变量指向JDK的安装...

Global site tag (gtag.js) - Google Analytics