目录
问题1:java文件如何在JVM上运行得到我们想要的结果?
通过Javac编译器,将java文件编译成为class字节码文件,字节码文件通过jvm装载,初始化,执行引擎输出结果。
问题2:为什么需要通过字节码文件,直接编译java文件不可以吗?
java的优势之一就是一次编译,随处运行,他的实现就是依赖于字节码在jvm上运行,能够脱离操作系统的限制,而且字节码指令语法,不仅仅让jvm支持java语言的运行,同时也支持其他可以编译成为字节码文件的编程语言,比如Kotlin,Scala等等。
一,class文件结构
文件的本质存储的二进制数据,为了方便查看,我们可以文件的十六进制格式数据,一个byte字节就展示成为两个十六进制数。通过IDEA的插件BinEd,可以将class文件可视化为指定进制文件,例如:
BinEd插件操作方法:第一步下载插件重启IDEA,第二步构建我们的java文件,获得class文件,第三步右键我们的class文件,选择Open as Binary即可打开。
class文件是以八个字节为基础单位的二进制文件,他的数据项严格按照顺序紧凑的排列在一起,中间没有分隔符,所以数据类型的规定显得格外重要。在class文件中,规定了两种大概念的数据类型:“无符号数”和“表”。
无符号数:规定了四种格式u1,u2,u4,u8,u后面的数字代表了字节数量,它可以用来描述数字,索引引用,数量值或者字符串的utf-8编码。
表:由多个无符号数或者其他的表构成复合数据类型,为了进行区分,习惯通过“_info”结尾。
1.1 魔数
每个class文件的开头四个字节被称为魔数,它是固定的CAFEBABE,代表了这个文件是一个class文件。后面四个字节,记录了这个class文件的版本号,也就是jdk的版本。56字节是次版本号,78字节是主版本号,jdk8的版本号是52,jdk6的版本号是50,有版本号的区别,class文件就不能随意放到不同版本的jvm中。
1.2 常量池
版本号之后,就是常量池,可以理解为class文件的资源仓库,它通常是占用class文件空间最大的部分,他的结构是表类型数据。由于常量的数量不固定的,所以需要需要一个u2类型数字去记录有多少个常量,如图所示:
图中表示这个class文件常量有34个,同时也规定了 常量的索引值是1至34,而其他索引都是从0开始的,这里从1开始, 是因为0空出来,是因为可以当作无索引值。常量池存放两大类型:字面量和符号引用。而且每一个常量都是一个表(所以类型都是info结尾的),
使用javap -v XX.class查看信息