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代码背后的底层视角,并可以帮助进行性能调优、代码审查和学习。文章来源:https://www.toymoban.com/news/detail-694091.html
然而,它仅限于处理已编译的类文件,并且反编译的源代码可能与原始Java代码存在一些语义差异。因此,在使用 javap
时需要注意其局限性,并结合其他工具和技术来进行全面的分析和理解。
文章来源地址https://www.toymoban.com/news/detail-694091.html
到了这里,关于【Java可执行命令】(四)反编译工具javap:深入解析应用程序反编译工具javap ~的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!