Java中类的编译执行过程

 

 

 

 

 

 

 

 

X.class文件执行Java命令被ClassLoader(类加载器)load到内存中,ClassLoader同时也会将Java的类库装载到内存中,装载完成后调用字节码的解释器,或者即时编译器,来进行解释或编译,编译完成后由执行引擎开始执行。执行引擎面对的则是硬件。

 

Java代码可以解释、编译混合执行,比较常用的代码(使用次数多)会做成本地编译(进行即时编译器编译),下次执行代码时就不再需要解释器解释执行了。

class文件解读

class文件是Java文件编译完成后的结果。

 

class文件包含的主要信息:

 

 

1、magic(magic_number)

 magic魔术四个字节,用来表明文件类型的,magic的值固定为0xCAFEBABE。作用是判断该文件是否为一个Java虚拟机接受的calss文件。任何类型的文件都会有类似的数据表示文件类型。

2、minor/major version 副/主版本号

各占两个字节副版本号与主版本号共同构成了class文件的版本号。譬如某个 Class 文件的主版本号为 M,副版本号为 m,那么这个Class 文件的格式版本号就确定为 M.m。一个 Java 虚拟机实例只能支持特定范围内的主版本号。不同版本的Java编译器编译的Class文件对应的版本是不一样的。高版本的虚拟机支持低版本的编译器编译的 Class文件结构。比如Java SE 6.0对应的虚拟机支持Java SE 5.0的编译器编译的Class文件结构,反之则不行。

3constant_pool_count常量计数器。

常量池计数器,constant_pool_count 的值等于 constant_pool 表中的成员数加 1constant_pool 表的索引值只有在大于 0 且小于 constant_pool_count 时才会被认为是有效的。

4、constant_pool常量池

 

major_version之后是常量池(constant_pool)的入口,它是Class文件中与其他项目关联最多的数据类型,也是占用Class文件空间最大的数据项目之一。常量池的编号从1开始。常量池中主要存放两大类常量:字面量(Literal)和符号引用(Symbolic References)。

 

5、访问标识(access_flag)

 

在常量池结束之后,紧接着的两个字节代表访问标志(access_flags),这个标志用于识别一些类或者接口层次的访问信息,包括:这个Class是类还是接口;是否定义为public类型;是否定义为abstract类型,如果是类的话,是否被声明为final等,具体的标志位以及标志的含义如下:

字面量比较接近于Java层面的常量概念,如文本字符串、被声明为final的常量值等。而符号引用总结起来则包括了下面三类常量:

  • 类和接口的全限定名(即带有包名的Class名,如:com.sunny.common.TestClass)
  • 字段的名称和描述符(private、static等描述符)
  • 方法的名称和描述符(private、static等描述符)

 虚拟机在加载Class文件时才会进行动态连接,也就是说,Class文件中不会保存各个方法和字段的最终内存布局信息,因此,这些字段和方法的符号引用不经过转换是无法直接被虚拟机使用的。当虚拟机运行时,需要从常量池中获得对应的符号引用,再在类加载过程中的解析阶段将其替换为直接引用,并翻译到具体的内存地址中。

符号引用与直接引用的区别和关联:

符号引用:符号引用以一组符号来描述所引用的目标,符号可以是任何形式的字面量,只要使用时能无歧义地定位到目标即可。符号引用与虚拟机实现的内存布局无关,引用的目标并不一定已经加载到了内存中。

直接引用:

直接引用可以是直接指向目标的指针、相对偏移量或是一个能间接定位到目标的句柄。直接引用是与虚拟机实现的内存布局相关的,同一个符号引用在不同虚拟机实例上翻译出来的直接引用一般不会相同。如果有了直接引用,那说明引用的目标必定已经存在于内存之中了。

 由于内容较多这里就不再整理了,想了解后面的细节可以参考文档:

https://www.jianshu.com/p/68520593b999      ------  本文也有很多内容是引用的这篇文章。

 



 

 

 

posted @ 2023-01-17 12:38  😂😂幺力儿园毕业😂😂  阅读(80)  评论(0)    收藏  举报