大家好,欢迎来到IT知识分享网。
Java可执行命令详解之javap
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 dc7403df8ac63066c97760fc56 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时需要注意其局限性,并结合其他工具和技术来进行全面的分析和理解。
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/112297.html
