- 把java文件编译生成class文件,
// 编写HelloByteCode.java
public class HelloByteCode {
public static void main(String[] args) {
HelloByteCode obj = new HelloByteCode();
}
}
- 通过命令行生成class文件
通过Android Studio idea 查看生成的class文件,由此也可以看出,默认构造函数就在这里生成了
// HelloByteCode.class
public class HelloByteCode {
public HelloByteCode() {
}
public static void main(String[] var0) {
new HelloByteCode();
}
}
其中javac有很多参数可用,可以通过javac --help查看
javac --help
用法: javac <options> <source files>
其中, 可能的选项包括:
@<filename> 从文件读取选项和文件名
-Akey[=value] 传递给注释处理程序的选项
--add-modules <模块>(,<模块>)*
除了初始模块之外要解析的根模块; 如果 <module>
为 ALL-MODULE-PATH, 则为模块路径中的所有模块。
--boot-class-path <path>, -bootclasspath <path>
覆盖引导类文件的位置
--class-path <path>, -classpath <path>, -cp <path>
指定查找用户类文件和注释处理程序的位置
-d <directory> 指定放置生成的类文件的位置
-deprecation 输出使用已过时的 API 的源位置
--enable-preview 启用预览语言功能。要与 -source 或 --release 一起使用。
-encoding <encoding> 指定源文件使用的字符编码
-endorseddirs <dirs> 覆盖签名的标准路径的位置
-extdirs <dirs> 覆盖所安装扩展的位置
-g 生成所有调试信息
-g:{lines,vars,source} 只生成某些调试信息
-g:none 不生成任何调试信息
-h <directory> 指定放置生成的本机标头文件的位置
--help, -help, -? 输出此帮助消息
--help-extra, -X 输出额外选项的帮助
-implicit:{none,class} 指定是否为隐式引用文件生成类文件
-J<flag> 直接将 <标记> 传递给运行时系统
--limit-modules <模块>(,<模块>)*
限制可观察模块的领域
--module <模块>(,<模块>)*, -m <模块>(,<模块>)*
只编译指定的模块,请检查时间戳
--module-path <path>, -p <path>
指定查找应用程序模块的位置
--module-source-path <module-source-path>
指定查找多个模块的输入源文件的位置
--module-version <版本> 指定正在编译的模块版本
-nowarn 不生成任何警告
-parameters 生成元数据以用于方法参数的反射
-proc:{none,only} 控制是否执行注释处理和/或编译。
-processor <class1>[,<class2>,<class3>...]
要运行的注释处理程序的名称; 绕过默认的搜索进程
--processor-module-path <path>
指定查找注释处理程序的模块路径
--processor-path <path>, -processorpath <path>
指定查找注释处理程序的位置
-profile <profile> 请确保使用的 API 在指定的配置文件中可用
--release <release> 针对特定发行版进行编译。支持的发行版:7, 8, 9, 10, 11, 12
-s <directory> 指定放置生成的源文件的位置
--source <release>, -source <release>
提供与指定发行版的源兼容性。支持的发行版:7, 8, 9, 10, 11, 12
--source-path <path>, -sourcepath <path>
指定查找输入源文件的位置
--system <jdk>|none 覆盖系统模块位置
--target <release>, -target <release>
生成针对特定 VM 版本的类文件。支持的版本:7, 8, 9, 10, 11, 12
--upgrade-module-path <path>
覆盖可升级模块位置
-verbose 输出有关编译器正在执行的操作的消息
--version, -version 版本信息
-Werror 出现警告时终止编译
其中javac -g HelloByteCode.java 可以生成测试信息,大家可以自行尝试
- 查看字节码
通过命令行方式
javap -c -verbose HelloByteCode.class
javap -c -verbose HelloByteCode.class
Classfile /Users/xxxDesktop/java/HelloByteCode.class
Last modified 2022年9月29日; size 288 bytes
MD5 checksum b572cf2c2ccd067ad41d5c137a875273
Compiled from "HelloByteCode.java"
public class HelloByteCode
minor version: 0
major version: 56
flags: (0x0021) ACC_PUBLIC, ACC_SUPER
this_class: #2 // HelloByteCode
super_class: #4 // java/lang/Object
interfaces: 0, fields: 0, methods: 2, attributes: 1
Constant pool:
#1 = Methodref #4.#13 // java/lang/Object."<init>":()V
#2 = Class #14 // HelloByteCode
#3 = Methodref #2.#13 // HelloByteCode."<init>":()V
#4 = Class #15 // java/lang/Object
#5 = Utf8 <init>
#6 = Utf8 ()V
#7 = Utf8 Code
#8 = Utf8 LineNumberTable
#9 = Utf8 main
#10 = Utf8 ([Ljava/lang/String;)V
#11 = Utf8 SourceFile
#12 = Utf8 HelloByteCode.java
#13 = NameAndType #5:#6 // "<init>":()V
#14 = Utf8 HelloByteCode
#15 = Utf8 java/lang/Object
{
public HelloByteCode();
descriptor: ()V
flags: (0x0001) 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 1: 0
public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: (0x0009) ACC_PUBLIC, ACC_STATIC
Code:
stack=2, locals=2, args_size=1
0: new #2 // class HelloByteCode
3: dup
4: invokespecial #3 // Method "<init>":()V
7: astore_1
8: return
LineNumberTable:
line 3: 0
line 4: 8
}
如果是带-g测试信息的class文件,效果是如下,多了额外的本地变量信息
javap -c -verbose HelloByteCode.class
Classfile /Users/hzhenx/Desktop/java/HelloByteCode.class
Last modified 2022年9月29日; size 415 bytes
MD5 checksum 05c705e182f58d3b5aa49c28d9e70d1d
Compiled from "HelloByteCode.java"
public class HelloByteCode
minor version: 0
major version: 56
flags: (0x0021) ACC_PUBLIC, ACC_SUPER
this_class: #2 // HelloByteCode
super_class: #4 // java/lang/Object
interfaces: 0, fields: 0, methods: 2, attributes: 1
Constant pool:
#1 = Methodref #4.#19 // java/lang/Object."<init>":()V
#2 = Class #20 // HelloByteCode
#3 = Methodref #2.#19 // HelloByteCode."<init>":()V
#4 = Class #21 // java/lang/Object
#5 = Utf8 <init>
#6 = Utf8 ()V
#7 = Utf8 Code
#8 = Utf8 LineNumberTable
#9 = Utf8 LocalVariableTable
#10 = Utf8 this
#11 = Utf8 LHelloByteCode;
#12 = Utf8 main
#13 = Utf8 ([Ljava/lang/String;)V
#14 = Utf8 args
#15 = Utf8 [Ljava/lang/String;
#16 = Utf8 obj
#17 = Utf8 SourceFile
#18 = Utf8 HelloByteCode.java
#19 = NameAndType #5:#6 // "<init>":()V
#20 = Utf8 HelloByteCode
#21 = Utf8 java/lang/Object
{
public HelloByteCode();
descriptor: ()V
flags: (0x0001) 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 1: 0
LocalVariableTable:
Start Length Slot Name Signature
0 5 0 this LHelloByteCode;
public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: (0x0009) ACC_PUBLIC, ACC_STATIC
Code:
stack=2, locals=2, args_size=1
0: new #2 // class HelloByteCode
3: dup
4: invokespecial #3 // Method "<init>":()V
7: astore_1
8: return
LineNumberTable:
line 3: 0
line 4: 8
LocalVariableTable:
Start Length Slot Name Signature
0 9 0 args [Ljava/lang/String;
8 1 1 obj LHelloByteCode;
}
SourceFile: "HelloByteCode.java"
其中可以看到多了
LocalVariableTable:
Start Length Slot Name Signature
0 9 0 args [Ljava/lang/String;
8 1 1 obj LHelloByteCode;
也可以通过Android Studio 的插件jclasslib可视化去查看
-
Android Stuido 安装插件
1. 打开Preferences
进入Plugins,搜索jclasslib
然后点击安装,重启ide
-
使用jclasslib查看字节码
IDE打开class文件
View->Show bytecode
至于怎么读懂字节码后面更新
网友评论