我们都知道Java是跨平台的语言,但是JVM并不能直接运行我们编写的 .java 后缀的文件,它需要被编译成 .class 各种的字节码文件后,才能被JVM 加载运行;白话一点:"JVM 只认 .class 文件,不认其他的文件";这也意味着只要你编写的代码能够被编译成正确的class文件,那么JVM就能够运行,这也使得基于JVM的语言变得枝繁叶茂,例如 Scala,Grovy...

小总结

Java 是跨平台的语言
JVM 是跨语言的平台

那么什么才是正确格式的class 文件呢,这点JVM规范做了规定,可以参考oracle官方文档

Class File Format

下图是Class文件的格式:

image.png

图中: u4代表长度是4个字节,以此类推u2代表长度是两个字节。

magic

魔数,固定值: 0xCAFEBABE.

minor_version, major_version

小版本号,大版本号;例如Java8 的版本号是 52,16进制是34

image.png

constant_pool_count

常量池梳理,这里的数值是实际数量+1,从1开始。

constant_pool

常量池信息

access_flags

访问控制标识

image.png

this_class

当前类信息,必须是一个有效的指向常量池的index

super_class

父类信息,必须是一个有效的指向常量池的index

interfaces_count

接口数量

interfaces[]

接口数组,必须是有效的指向常量池的index

field_counts

成员变量数量

fields[]

field_info格式的数组

methods_count

方法数量

methods[]

method_info格式的数组

attributes_count

属性数量

attributes[]

attribute_info格式的数组

Field Info 的格式
image.png

access_flags

访问控制标识

image.png

name_index

名称索引,必须是一个有效的指向常量池的下标

descriptor_index

描述符索引,必须是一个有效的指向常量池的下标

attributes_count

属性数量

attributes[]

attribute_info结构的数组

Method Info 的格式

image.png

access_flags

访问控制标识

image.png

name_index

名称索引,必须是一个有效的指向常量池的下标

descriptor_index

描述符索引,必须是一个有效的指向常量池的下标

attributes_count

属性数量

attributes[]

attribute_info结构的数组

Attributes Info 的格式

image.png

attribute_name_index

属性名称索引,必须是一个有效的指向常量池的下标

attribute_length

属性长度

info

信息

二进制/十六进制编辑器

插件市场搜索 BinEd 并安装

image.png

File 中使用Open as binary 查看或编辑指定class文件

image.png

image.png

字节码解析工具

插件市场搜索 jclasslib 并安装

image.png

选中指定类,在view 视图中选择 Show ByteCode with jclasslib
image.png

image.png