zoukankan      html  css  js  c++  java
  • @使用javap反编译Java字节码文件

    在Sun公司提供的JDK中,就已经内置了Java字节码文件反编译工具javap.exe(位于JDK安装目录的bin文件夹下)。

    我们可以在dos窗口中使用javap来反汇编指定的Java字节码文件。在使用javap的相关dos命令之前,你必须确保已经将JDK安装目录in添加到环境变量path中。

    接着,我们就可以使用javap来反编译指定的Java字节码文件了。在此之前,我们先通过javap的帮助命令javap -help查看javap相关指令的用法。

    C:Userswinner_0715>javap -help
    用法: javap <options> <classes>
    其中, 可能的选项包括:
      -help  --help  -?        输出此用法消息
      -version                 版本信息
      -v  -verbose             输出附加信息
      -l                       输出行号和本地变量表
      -public                  仅显示公共类和成员
      -protected               显示受保护的/公共类和成员
      -package                 显示程序包/受保护的/公共类
                               和成员 (默认)
      -p  -private             显示所有类和成员
      -c                       对代码进行反汇编
      -s                       输出内部类型签名
      -sysinfo                 显示正在处理的类的
                               系统信息 (路径, 大小, 日期, MD5 散列)
      -constants               显示最终常量
      -classpath <path>        指定查找用户类文件的位置
      -cp <path>               指定查找用户类文件的位置
      -bootclasspath <path>    覆盖引导类文件的位置

    从上述内容我们可以知道,javap的使用命令格式为javap 选项参数 类名,其中选项参数可以有多个,中间用空格隔开,也可以一个都没有。下面我们编写如下源代码文件(包名test,类名Person),并将其编译为Person.class字节码文件。

    package test;
    
    public class Person {
        public Person(String name, int age, boolean gender, String address) {
            this.name = name;
            this.age = age;
            this.gender = gender;
            this.address = address;
        }
    
        // private修饰符
        private String name;
        // 默认无访问修饰符(即下面所说的package、friendly)
        int age;
        // protected修饰符
        protected boolean gender;
        // public修饰符
        public String address;
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public void sayHi() {
            System.out.println("Hello, my name is " + this.name);
        }
    }

    接着将包名文件夹test及Person.class放置在D:java目录下。以便于我们使用javap命令进行测试。

    在执行命令之前,我们需要将dos窗口的当前工作目录变更为D:java est

    1、使用不带任何选项参数的命令:javap Person

    D:java	est>javap Person
    警告: 二进制文件Person包含test.Person
    Compiled from "Person.java"
    public class test.Person {
      int age;
      protected boolean gender;
      public java.lang.String address;
      public test.Person(java.lang.String, int, boolean, java.lang.String);
      public java.lang.String getName();
      public void setName(java.lang.String);
      public void sayHi();
    }

    javap Person和javap -package Person的显示结果一样,因为-package选项参数是默认的,用于显示package(不带任何访问修饰符,即我们常说的friendly)、protected、public修饰的类或成员。不会显示私有成员的属性

    备注:在dos下进入工作目录D:java,然后使用命令javap test.Person也可以实现上述操作。下同。

    2、使用命令:javap -public Person显示public修饰的类或成员。

    D:java	est>javap -public Person
    警告: 二进制文件Person包含test.Person
    Compiled from "Person.java"
    public class test.Person {
      public java.lang.String address;
      public test.Person(java.lang.String, int, boolean, java.lang.String);
      public java.lang.String getName();
      public void setName(java.lang.String);
      public void sayHi();
    }

    与此类似,选项参数-protected用于显示protected以上访问级别(protected、public)的类或成员;选项参数-private用于显示private以上访问级别,也就是所有的类或成员。

    3、使用命令:javap -public -l Person显示public修饰的类或成员,并显示行号表格和本地变量表格。

    D:java	est>javap -public -l Person
    警告: 二进制文件Person包含test.Person
    Compiled from "Person.java"
    public class test.Person {
      public java.lang.String address;
    
      public test.Person(java.lang.String, int, boolean, java.lang.String);
        LineNumberTable:
          line 4: 0
          line 5: 4
          line 6: 9
          line 7: 14
          line 8: 19
          line 9: 25
        LocalVariableTable:
          Start  Length  Slot  Name   Signature
              0      26     0  this   Ltest/Person;
              0      26     1  name   Ljava/lang/String;
              0      26     2   age   I
              0      26     3 gender   Z
              0      26     4 address   Ljava/lang/String;
    
      public java.lang.String getName();
        LineNumberTable:
          line 21: 0
        LocalVariableTable:
          Start  Length  Slot  Name   Signature
              0       5     0  this   Ltest/Person;
    
      public void setName(java.lang.String);
        LineNumberTable:
          line 25: 0
          line 26: 5
        LocalVariableTable:
          Start  Length  Slot  Name   Signature
              0       6     0  this   Ltest/Person;
              0       6     1  name   Ljava/lang/String;
    
      public void sayHi();
        LineNumberTable:
          line 29: 0
          line 30: 28
        LocalVariableTable:
          Start  Length  Slot  Name   Signature
              0      29     0  this   Ltest/Person;

    4、使用命令:javap -c Person显示Person.class反汇编出的字节码命令。

    D:java	est>javap -c Person
    警告: 二进制文件Person包含test.Person
    Compiled from "Person.java"
    public class test.Person {
      int age;
    
      protected boolean gender;
    
      public java.lang.String address;
    
      public test.Person(java.lang.String, int, boolean, java.lang.String);
        Code:
           0: aload_0
           1: invokespecial #1                  // Method java/lang/Object."<init>":()V
           4: aload_0
           5: aload_1
           6: putfield      #2                  // Field name:Ljava/lang/String;
           9: aload_0
          10: iload_2
          11: putfield      #3                  // Field age:I
          14: aload_0
          15: iload_3
          16: putfield      #4                  // Field gender:Z
          19: aload_0
          20: aload         4
          22: putfield      #5                  // Field address:Ljava/lang/String;
          25: return
    
      public java.lang.String getName();
        Code:
           0: aload_0
           1: getfield      #2                  // Field name:Ljava/lang/String;
           4: areturn
    
      public void setName(java.lang.String);
        Code:
           0: aload_0
           1: aload_1
           2: putfield      #2                  // Field name:Ljava/lang/String;
           5: return
    
      public void sayHi();
        Code:
           0: getstatic     #6                  // Field java/lang/System.out:Ljava/io/PrintStream;
           3: new           #7                  // class java/lang/StringBuilder
           6: dup
           7: invokespecial #8                  // Method java/lang/StringBuilder."<init>":()V
          10: ldc           #9                  // String Hello, my name is
          12: invokevirtual #10                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
          15: aload_0
          16: getfield      #2                  // Field name:Ljava/lang/String;
          19: invokevirtual #10                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
          22: invokevirtual #11                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
          25: invokevirtual #12                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
          28: return
    }

    由于选项参数之间组合较多,因此其他选项参数不再一一截图赘述,仅在下面使用文字进行说明:

    -classpath <pathlist>
    手动指定用户class字节码文件的存放目录,javap程序将在此目录下查找class文件,多个路径以英文分号分隔。例如:javap -classpath D:java est Person(即使DOS窗口的当前工作目录为其他任意路径,该命令均可正确执行)。
    -s
    打印变量的内部类型签名,例如:javap -classpath D:java est -s Person。
    -extdirs <dirs>
    指定javap搜索已安装的java扩展的位置,默认的java扩展的位置为jrelibext。例如:javap -classpath D:java est -extdirs D:javamyext Person
    -bootclasspath <pathlist>
    指定使用Java底层类加载器(bootstrap class loader)加载的字节码文件的位置。例如:javap -classpath D:java est -bootclasspath D:javacore Person
    -verbose
    打印方法参数和本地变量的数量以及栈区大小。
    -J<flag>
    使用javap.exe来执行java.exe虚拟机的相关命令,例如javap -J-version相当于java -version,可以有多个命令,中间以空格隔开。
  • 相关阅读:
    华为FusionCloud云计算vCPU资源计算公式(MHz)
    Jenkins入门总结
    前端构建工具gulp使用 (转)
    大窍决:放松,放松,再放松! 高僧开示汇编
    万物在这种绝对真性中自然解脱! 顶果钦哲仁波切
    阿姜查:为何我们生于此?|这个世界的真相
    与「法」同住世间
    阿姜查:哪里有迷妄,哪里便有平静
    阿姜查:不必让自己成为什么 一切顺其自然就好
    阿姜查:当心碰到外尘时,才是真正修行的开始
  • 原文地址:https://www.cnblogs.com/winner-0715/p/7150041.html
Copyright © 2011-2022 走看看