【Java可执行命令】(四)反编译工具javap:深入解析应用程序反编译工具javap ~

Java可执行命令详解之javap

  • 1️⃣ 概念
  • 2️⃣ 优势和缺点
  • 3️⃣ 使用
    • 3.1 语法格式
      • 3.1.1 可选参数:-l
      • 3.1.2 可选参数:-c
      • 3.1.3 可选参数:-s
      • 3.1.4 可选参数:-verbose
      • 3.1.5 可选参数:-version
  • 4️⃣ 应用场景
  • 5️⃣ 注意事项
  • 🌾 总结

在这里插入图片描述

1️⃣ 概念

javap是Java开发工具包(JDK)提供的一个命令行工具,用于反编译Java字节码。它旨在帮助开发人员深入了解和分析已编译的Java类文件。

javap可以将Java类文件解析为易于阅读的文本形式,展示其中的信息以及反编译出类的结构、方法、字段、常量池等信息。通过阅读和分析这些信息,开发人员可以更好地理解Java类的内部实现,并进行性能调优、代码审查等操作。

javap主要有以下作用:

  • 展示Java类的结构:可以从字节码级别上查看类的继承关系、方法和字段的信息;
  • 反编译Java字节码:将已编译的Java类文件转化为人可读的源代码形式,以便进行分析和理解。

javap通过解析Java类文件的字节码数据,并根据Java虚拟机规范定义的格式和约定,将其转化为易于阅读的文本形式。它使用反射和解析技术来获取类的结构和信息,并进行适当的格式转换和展示。

2️⃣ 优势和缺点

优点

  • 提供了一种方式来观察高级Java代码背后的底层字节码;
  • 可以帮助开发人员更好地理解Java类,并对其进行调试和优化;
  • 通过查看反编译的源代码,可以学习他人代码的实现细节。

缺点

  • 反编译出来的源代码可能不够清晰和易读,因为字节码和原始Java代码之间存在一些语义上的差异;
  • javap只能处理已编译的类文件,无法直接作用于源代码。

3️⃣ 使用

3.1 语法格式

javap的使用语法格式如下:

javap [options] <classname>

其中,[options]为可选参数列表,<classname>表示要解析的Java类名称。

javap命令支持许多可选参数来控制反编译过程。汇总全部的可选参数如下表:

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

下面主要介绍以下一些常用的 javap 可选参数:

  • -l: 显示行号和局部变量表信息;
  • -c: 显示Java字节码指令;
  • -s: 显示内部类型签名;
  • -verbose: 详细输出各个类的除了方法主体以外的信息;
  • -version: 显示版本信息。

3.1.1 可选参数:-l

javap -l命令用于在输出中显示行号和局部变量表信息。如果不使用-l选项,则只会显示基本的类和方法信息。下面是一个使用案例:

先使用 javac命令将Java源代码编译为字节码文件,成功编译后,将会生成一个.class的文件。然后就可以使用javap -l <类名>命令查看该类的字节码信息。在终端中执行以下命令:

javap -l MyClass

运行上述命令后,将显示如下输出:

Compiled from "MyClass.java"
public class com.xiaoshan.MyClass {
  public com.xiaoshan.MyClass();
    LineNumberTable:
      line 5: 0
    LocalVariableTable:
      Start  Length  Slot  Name   Signature
          0       5     0  this   Lcom/xiaoshan/MyClass;

  public static void main(java.lang.String[]);
    LineNumberTable:
      line 7: 0
      line 8: 8
    LocalVariableTable:
      Start  Length  Slot  Name   Signature
          0       9     0  args   [Ljava/lang/String;
}

这个输出告诉我们MyClass类有两个成员方法:默认的构造函数MyClass()和静态方法main(String[])。并且还打印出来了行号和局部变量表信息。

3.1.2 可选参数:-c

javap -c命令用于在输出中显示字节码指令信息。下面是一个使用案例:

在终端中执行以下命令:

javap -c MyClass

运行上述命令后,会输出包含字节码指令的详细列表。每个指令都与其对应的操作和参数一起显示。显示如下输出:

Compiled from "MyClass.java"
public class com.xiaoshan.MyClass {
  public com.xiaoshan.MyClass();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  public static void main(java.lang.String[]);
    Code:
       0: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
       3: ldc           #3                  // String Hello world!
       5: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
       8: return
}

在以上示例中,我们可以看到反汇编的 MyClass 类的 默认的构造函数MyClass()和静态方法main(String[])的字节码指令列表。
通过使用 javap -c 命令,你可以深入了解 Java 字节码,并查看所编译类文件中的相应指令。这对于理解代码的底层实现和进行调试非常有用。

3.1.3 可选参数:-s

javap -s 命令可以显示与指定类相关的字节码指令及其源代码的符号信息。以下是关于该命令的作用和使用方式的演示:

使用 javap -s MyClass 命令来查看 MyClass.class 文件的字节码指令及其对应的源代码符号信息:

javap -s MyClass

运行上述命令后,将输出包含字节码指令和源代码符号信息的详细列表。每个指令都与其对应的操作、参数和源代码行号一起显示。
输出结果:

Compiled from "MyClass.java"
public class com.xiaoshan.MyClass {
public com.xiaoshan.MyClass();
 descriptor: ()V

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

在以上示例中,我们可以看到反汇编的 MyClass 类的 main 方法的字节码指令及其源代码符号信息。

通过使用 javap -s 命令,你可以深入了解 Java 字节码及其与源代码之间的映射关系。这对于调试和理解代码执行非常有用,因为它提供了包括本地变量、操作数栈、异常处理器等在内的更多详细信息。

3.1.4 可选参数:-verbose

javap -verbose 是一个用于反汇编 Java 字节码并显示更详细信息的命令,它可以显示与指定类相关的字节码指令、常量池、方法、字段和其他类信息。

以下是关于该命令的作用和使用方式的演示:

使用 javap -verbose MyClass 命令来查看 MyClass.class 文件的更详细反汇编信息:

javap -verbose MyClass

运行上述命令后,将输出包含字节码指令、常量池、方法、字段和其他类信息的详细列表。

输出结果:

Classfile /C:/Users/86182/IdeaProjects/untitled15/src/com/xiaoshan/MyClass.class
  Last modified 2023-6-28; size 551 bytes
  MD5 checksum 349388dc7403df8ac63066c97760fc56
  Compiled from "MyClass.java"
public class com.xiaoshan.MyClass
  minor version: 0
  major version: 52
  flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
   #1 = Methodref          #6.#20         // java/lang/Object."<init>":()V
   #2 = Fieldref           #21.#22        // java/lang/System.out:Ljava/io/PrintStream;
   #3 = String             #23            // Hello world!
   #4 = Methodref          #24.#25        // java/io/PrintStream.println:(Ljava/lang/String;)V
   #5 = Class              #26            // com/xiaoshan/MyClass
   #6 = Class              #27            // java/lang/Object
   #7 = Utf8               <init>
   #8 = Utf8               ()V
   #9 = Utf8               Code
  #10 = Utf8               LineNumberTable
  #11 = Utf8               LocalVariableTable
  #12 = Utf8               this
  #13 = Utf8               Lcom/xiaoshan/MyClass;
  #14 = Utf8               main
  #15 = Utf8               ([Ljava/lang/String;)V
  #16 = Utf8               args
  #17 = Utf8               [Ljava/lang/String;
  #18 = Utf8               SourceFile
  #19 = Utf8               MyClass.java
  #20 = NameAndType        #7:#8          // "<init>":()V
  #21 = Class              #28            // java/lang/System
  #22 = NameAndType        #29:#30        // out:Ljava/io/PrintStream;
  #23 = Utf8               Hello world!
  #24 = Class              #31            // java/io/PrintStream
  #25 = NameAndType        #32:#33        // println:(Ljava/lang/String;)V
  #26 = Utf8               com/xiaoshan/MyClass
  #27 = Utf8               java/lang/Object
  #28 = Utf8               java/lang/System
  #29 = Utf8               out
  #30 = Utf8               Ljava/io/PrintStream;
  #31 = Utf8               java/io/PrintStream
  #32 = Utf8               println
  #33 = Utf8               (Ljava/lang/String;)V
{
  public com.xiaoshan.MyClass();
    descriptor: ()V
    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 5: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       5     0  this   Lcom/xiaoshan/MyClass;

  public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=1, args_size=1
         0: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
         3: ldc           #3                  // String Hello world!
         5: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
         8: return
      LineNumberTable:
        line 7: 0
        line 8: 8
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       9     0  args   [Ljava/lang/String;
}
SourceFile: "MyClass.java"

在以上示例中,我们可以看到反汇编的 MyClass 类的文件信息、版本信息、类访问标志、常量池、方法信息和其他相关信息。

通过使用 javap -verbose 命令,你可以深入了解 Java 字节码及其与类结构、常量池和其他组件之间的关联。这对于分析代码执行过程和理解内部实现非常有用。

3.1.5 可选参数:-version

javap -version 可以用来查看类文件的版本信息的。以下是关于该命令的作用和使用方式的演示:

使用 javap -version MyClass 命令来查看 MyClass.class 文件的版本信息:

javap -version MyClass

运行上述命令后,将输出 MyClass.class 文件的版本等信息。 输出结果:

1.8.0_162
Compiled from "MyClass.java"
public class com.xiaoshan.MyClass {
 public com.xiaoshan.MyClass();
 public static void main(java.lang.String[]);
}

在以上示例中,我们可以看到反汇编的 MyClass 类的类文件版本为 1.8.0_162。
通过使用 javap -version 命令,你可以查看指定 Java 类的类文件版本信息。这对于了解类的兼容性和所需的 Java 运行时环境版本有用。

4️⃣ 应用场景

javap广泛应用于以下场景:

  • 代码审查:通过查看反编译的源代码,可以对他人代码的实现细节进行分析和评估;
  • 性能调优:可以通过阅读字节码指令、查看局部变量信息等来进行性能分析和优化;
  • 学习和教学:对于想深入理解Java语言机制、字节码执行等底层原理的学生和教师,javap提供了一种友好的方式来观察和学习。

5️⃣ 注意事项

在使用 javap时需要注意以下事项:

  • javap只能处理已编译的类文件(.class文件),不能直接作用于源代码(.java文件);
  • 反编译结果可能不完全等同于原始Java代码,因为字节码和源代码之间存在语义上的差异;
  • javap只能解析公共类和成员,默认情况下无法访问非公共或非静态成员。

🌾 总结

javap是一个有用的工具,用于反编译Java字节码,了解和分析类的内部实现和结构。它为开发人员提供了一个透视Java代码背后的底层视角,并可以帮助进行性能调优、代码审查和学习。

然而,它仅限于处理已编译的类文件,并且反编译的源代码可能与原始Java代码存在一些语义差异。因此,在使用 javap时需要注意其局限性,并结合其他工具和技术来进行全面的分析和理解。

文章出处登录后可见!

已经登录?立即刷新

共计人评分,平均

到目前为止还没有投票!成为第一位评论此文章。

(0)
xiaoxingxing的头像xiaoxingxing管理团队
上一篇 2023年12月12日
下一篇 2023年12月12日

相关推荐