JVM | 浅谈Class文件的结构

Java与JVM

第一天学习Java的时候我们就接触到了JVM,当时老师告诉我们:JVM是Java语言的运行环境…但是JVM并不是只能运行Java程序,诸如Scala、Kotlin、Groovy、JRuby等程序语言编写的程序都能够在JVM上运行,原因就在于JVM并不是和任何语言程序绑定,而是只要是符合《Java虚拟机规范》的Class文件,不管是它是什么语言编译而成的,都可以在JVM上运行。借助一张图来描述此类程序语言和JVM的关系:

Class文件与平台无关性

这里所说的Class文件并不仅仅包含文件系统上的.class文件,而是一组有严格规范的二进制流,所以就无关乎来源是文件、网络资源、动态构建等等了,只要能够在程序中读取成符合规范的二进制流,就可以被JVM加载。正是因为JVM只识别这种字节码,所以才成就了Java语言的平台无关性,只要针对不同OS的特性实现统一规范的javac编译器和JVM,就可以在不同OS环境下编译执行同一份Java文件。即同一份Java文件在不同的系统中,使用不同的javac编译成了同一份Class文件,然后在不同系统的JVM中运行得到了相同的输出。

程序是没办法直接控制cpu、网卡、键盘等物理硬件的,而是调用OS提供的接口,然后由OS去控制物理硬件。Java的跨平台特性在于JVM向上提供了统一的接口供程序调用,JVM向下再去调用OS提供的接口,我们就无需关心不同OS提供的接口的差异性了,所以说JVM的不跨平台性实现了Java语言的跨平台性。

Class文件的结构

Class文件是一组以8个字节为基础单位的二进制流,各个数据项目严格按照顺序紧凑地排列在文件之中,中间没有添加任何分隔符,这使得整个Class文件中存储的内容几乎全部是程序运行的必要数据,没有空隙存在。当遇到需要占用8个字节以上空间的数据项时,则会按照高位在前的方式分割成若干个8个字节进行存储。
上面这段话出自周志明老师的《深入理解Java虚拟机》,书中利用很大的篇幅对class文件的结构进行了逐字解释,这里的讨论只是展示class文件各部分包含了哪些数据,帮助理解,下图展示了一个class文件中所包含的数据。

魔数

开头的cafebabe即我们经常说的魔数,其实很多文件的开头都会有魔数,唯一的用处就是用来表示文件的格式。

版本号

魔数之后紧跟着的是class文件的版本号,分为小版本号和大版本号,小版本号在前。版本号的大小是根据jdk的版本生成的,jdk 版本越大,版本号也越大,它的作用在于限定高版本的jdk只能向下兼容低版本的class文件, 不能兼容高版本的class文件,避免出现安全问题。

常量池

这里的常量池并非我们所理解的JVM内存中的常量池,它主要包含了该class文件中的字面量和符号引用,譬如文本字符串、字段名、方法名、类名等等都存在于常量池中,下面是通过javap编译的class文件,可以更直观的理解常量池中的数据。可见常量池的长度是可变的,class中字段名、方法名等越多,常量池就会越长,所以在常量池的前面用一个数标识了常量池的长度。

访问标志

常量池之后是访问标志,用于识别一些类或者接口层次的访问信息。简单来说就是指明这个class文件是一个类还是接口、枚举等,访问权限是public还是其他权限,是否是抽象类和接口。

类索引、父类索引与接口索引集合

再往后记录了这个类的索引、夫类的索引、接口的索引,都是全限定符。由于Java中一个类可以实现多个接口,所以在记录接口索引前也会有一个数来标记接口的数量。这里实际上记录的是几个索引值,引用了前面所说的常量池中的数据。

字段表集合

一个类的字段的个数是不定的,所以在字段表集合前会有一个数来确定字段的个数。字段表集合中记录了字段的访问权限、类型、名称信息等,实际的记录值包括访问标志和索引值。

方法表集合

跟字段表集合类似,记录了方法的访问类型、名称索引、描述符索引、属性表集合。

属性表集合

属性表集合记录了很多东西,包括方法的具体代码编译后的字节码指令、方法抛出的异常列表、final定义的常量值、Java源码的行号与直接码的对应关系、源文件名称等等,具体的参考原书中的截图:

小结

本文主要简单阐述了我所理解的Class文件的构成,通过图示的方法展示了Class文件中主要包含的数据,为之后类加载相关的学习累积一些知识,意图不在于仔细研究。如果理解上有不对的地方,请各位大佬指教,不甚感激!

欢迎订阅我的博客:杰尼鸭
原文链接:https://www.jnduck.com/?p=67

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值