字节码?原来如此!
目录
第一步: javac A.java 编译生成 A.class
第二步: 使用 javap -c A.class 或 javap -verbose A.class 都可查看字节码文件
原文链接:https://blog.****.net/mengfanzhundsc/article/details/106365027
-
什么是字节码?
-
字节码结构
-
魔数:
- 对应Test.class 字节码文件中,魔数是0XCAFE BABE 。是用来区分文件类型的一种标志,一般都是用文件的前几个字节来表示。比如0XCAFE BABE表示的是class 文件。因为文件名包括后缀是可以修改的,所以为了保证文件的安全性,将文件类型写入了文件内容中来保证不被篡改。翻译过来就是咖啡宝贝意思,和Java 咖啡logo 保持呼应。
-
版本号:
- 版本号含主版本号和次版本号。都各占2个字节byte 。
- 对应Test.class 字节码文件中,版本号是0X0000 0034 。其中前面0000是副版本号minor_version,后面0034 是主版本号major_version。
- 进制转换后副版本号0,主版本号52. 从oralce 官网得知,52对应的正式jdk1.8 ,次版本号为0,所以该文件的版本为1.8.0 。
- 参考如下:
-
Access_flags访问标志
- Access_flags 描述的事当前类(或接口)的访问修饰符。如public,private等
-
当前类名
- 访问标志后的两个字节,描述的是当前类的全限定名。这两个字节保存的值为常量池中的索引值,根据索引值就能在常量池中找到这个类的全限定名。
-
父类名称
- 当前类名后的两个字节,描述父类的全限定名,同上,保存的也是常量池中的索引值。
-
接口信息
- 父类名称后为两字节的接口计数器,描述了该类或父类实现的接口数量。紧接着 的 n 个字节是所有接口名称的字符串常量的索引值。
-
字段表
- fields_info 用于描述接口或者类中声明的变量、字段包括类级以及实例级变量,但是不包括在方法内部声明的局部变量;
- 第一部分为字段计数器,占两个字节,描述字段个数;
- 第二部分是每个字段的详细信息 fields_info。结构如下:
- name_index:表示field 的名称-字段名
- descriptor_index:表示field的类型描述符(字段类型描述符)用来描述字段的数据类型,方法的参数列表和返回值
- 字段的访问标志:
-
方法表
- 方法表结构:
- 第一部分:方法计数器,占两个字节,描述方法个数;
- 第二部分:方法数据区,描述方法的详细信息,结构如下:
- name_index: 方法名称
- descriptor_index: 方法描述符,描述方法的参数列表返回值等,参数列表在前 返回值在后
- 执行命令 javap -verbose A.class 将其反编译为解读,可见方法数据区的内容分为3个部分:
- “Code 区”:源代码对应的JVM 指令操作码,在进行字节码增强时重点操作的就是“Code 区”这一部分。
- “LineNumberTable”:行号表, 将 Code 区的操作码和源代码中的行号对应,Debug 时会起到作用(源代码走一行,需要走多少个 JVM 指令操作码)。
- “LocalVariableTable”:本地变量表,包含 This 和局部变量,之所以可以在每一个方法内部都可以调用This, 是因为 JVM 将 This 作为每一个方法的第 一个参数隐式进行传入。当然,这是针对非 Static 方法而言。
-
附加属性表
- 字节码的最后一部分,该项存放了在该文件中类或接口所定义属性的基本信息。
-
有哪些操作查看字节码?
-
第一步: javac A.java 编译生成 A.class
-
第二步: 使用 javap -c A.class 或 javap -verbose A.class 都可查看字节码文件
-