前边 Java内存区域管理 中我们学习总结了JVM这个容器的内存空间区域划分,垃圾回收(GC Garbage Collection)中学习总结了JVM对容器中的对象是如何进行回收处理的。好,那么接下来,我们来看看,是什么样的对象在JVM中运行实现我们想要的业务效果呢?
我们IT技术人员,都会写代码,什么数据类型,什么数据结构,什么算法,什么面向对象……就Java技术而言,我们用.java类型文件来实现我们的各种想法。学习Java最开始,都知道编译期,运行期。学号的Java文件,要编译为.class文件,才能运行。好,重点.class文件,就是可以运行JVM上的文件。不仅仅是JAVA语言,其它语言编译后成为.class文件也可以在JVM中运行。
好,我们先看个小例子,看看JAVA中的.java文件内容及编译后的.class文件内容:
package functionpage;
public class Demo {
private int a = 1;
public void testMethod() {
System.out.println(a);
}
}
我们来看看.class文件的文件结构,由两种数据类型:无符号数(基本类型,类似Java的基本数据类型)和表(复合数据类型,类似Java中的集合)组成:
名称 | 描述 |
---|---|
magic-魔数 | 每个Class文件的头4个字节,唯一作用是确定这个文件是否为一个能被JVM接受的class文件。例如上图:CAFEBABE-cafe babe,咖啡宝贝,是不是挺有意思。 |
minor-version-次版本 | 2个字节,为此版本号 |
major-version-主版本 | 2个字节,为主版本号。表示JDK的版本(主次版本和我们平时代码版本管理一样),高版本向下兼容。例如用JDK1.8编译的class文件就不能放在jdk6上运行。 |
constant_pool_count-常量个数 | 2个字节,表示常量池中常量的个数,从1开始计数。 |
constant_pool-常量池 | 1-class文件中的资源仓库,为class文件结构中与其它项目关联最多的数据类型,也是最占用class文件空间,为表类型的数据项目。 2-包含:字面量(Literal)如文本字符串、声明的final的常量值等。 3-包含:符号引用(Symbolic References)如类、接口、字段、方法 具体的字面量,符号引用,可以看下这篇文章:https://blog.csdn.net/hxcaifly/article/details/82887552 |
access_flags-访问标识 | 2个字节用于识别,是否为public类型,是否被声明为final,是否为接口、是否为abstract类型,是否为用户代码生产,是否是注解,是否是枚举…… |
this_class-类索引 | 2个字节,用来确定这个类的全限定名,指向常量池中的CONSTANT_Class_info |
super_class-父类索引 | 2个字节,用来确定这个类的父类的全限定名,一个类只能有一个父类,指向常量池中的CONSTANT_Class_info |
interfaces_count | 接口个数 |
interfaces | 接口集合,接口从左到右排列的全限定名,指向常量池中的CONSTANT_Class_info |
fields_count | 字段个数 |
fields | 1-字段表,用于描述声明的变量,例如:作用域(public、private、protected修饰符),否是static,final,valatile,transient序列化,字段数据的类型(基本类型、对象、数组),字段名称等 2-修饰符用标志位描述,字段类型,需要引用常量池中的常量来描述,字段名称 |
methods_count | 方法个数 |
methods | 1-方法表,用于描述方法,和字段表差不多,除了valatile,transient没有 |
attributes_count | 属性的个数 |
attributes | 属性表:用于描述字段值、方法代码、异常、类文件等不同场景专有的信息。在上边的class文件、字段表、方法表等的具体描述中都会用到。 |
通过这个表格,可以看到其实.class文件就是.java的文件的另一种表示方式,都是通过字节码,来进行表述我们写的代码呢。由于更接近机器识别码,所以我们读起来相对比较困难。(大家都知道机器只认0和1,机器用0和1描绘了大千世界)。 是用JVM识别读取的。
好了,今天简单了解一下.class文件的结构。继续。。。