从JVM设计者的角度来看.class文件结构,一文弄懂.class文件的身份地位

目录java

本文相关虚拟机的命令

  1. 编写Java源码
Java源码
Java源码
  1. 编译指令 javac xxx.java,获得.class文件
  2. hexdump -C filename能够查看二进制文件
.class 二进制文件
.class 二进制文件
  1. 编译后使用 javap -c 类名, 获得.class文件对应的虚拟机指令 class文件对应的虚拟机指令
class文件对应的虚拟机指令表
class文件对应的虚拟机指令表

这里先让你们大体的看看.class文件和虚拟机指令的样子,不会让你有种“所爱隔山海”的感受。linux

Class文件产生背景及重要地位

【问题】只有Java语言编译后的class文件才能在 JVM 里面跑吗?

首先抛一个问题,是否是只有Java语言编译后的class文件才能在jvm中运行,也就是说其余的语言是否可使用Java虚拟机做为媒介? 答案是:不是,能够的;只要符合JVM文件结构的规范,编译后的文件均能运行,好比scala语言.scala结尾文件,能够编译为.class文件,能够在jvm中运行,哈哈哈,这里写的好生硬。web

各类语言与JVM的爱恨情仇
各类语言与JVM的爱恨情仇

如图各类语言与JVM的爱恨情仇,只要你的语言通过本身的编译器,最终能获得一个JVM须要的.class文件,那么你就能够。windows

class文件的地位

  • Source: 源码
  • Class: 字节码
  • Runtime: 运行时

字节码形态经由Classloader加载变成运行时形态(内存中)。jvm

java 刚刚诞生的口号“一次编写,处处运行",这是知足开发人员对冲破平台限制渴望的实现,这个很快就实现。然而设计者一开始发布规范文档的时候就是刻意把Java规范拆解成了《Java语言规范》和《Java虚拟机规范》,也就是说他们对虚拟机的野心不止于Java语言,他们将来的目标是冲破语言限制,如今也实现了,Scala,jRuby这些语言均可以运行在Java虚拟机上面。随着平台(windows,linux,unix)基本稳定,而语言突飞猛进,往后JAVA“语言无关”的优点可能会超过“平台无关”的优点!编辑器

实现语言无关的关键就是虚拟机和字节码存储格式。能够理解成虚拟机给你提供一个接口,你只须要按照他指定的格式传class文件给他,他即可以运行你的代码,因此关键就是这个class文件。虚拟机不关心你的项目使用什么语言进行代码实现,最后你只须要按照他想要的class格式编译成class文件传给他,就能够成功运行在虚拟机上面。我说的够清楚了吧老弟?ide

Class 类文件结构设计解析

class 文件是一组以8位字节为基础单位的二进制流,中间没有任何分隔符,正是由于没有任何分隔符因此class文件里面的数据项在顺序和数量上面是严格限定的,每一个字节的含义,长度,前后顺序,都不容许改变。具体class文件内容看图。idea

class文件采用的是一种相似于C语言结构体的伪结构来存储数据,本质就是一张表,如图所示:spa

.class 二进制文件
.class 二进制文件
class文件对应内容
class文件对应内容

【问题】你会怎么设计class文件?

首先抛出一个问题,JVM一开始就是服务Java的,拿Java语言来举例子,若是你是设计者,你将你的Java源码编译成class文件,你会怎么设计这个class文件?scala

思路:转换成容易理解的实现,知道Java的,通常都知道xml文件,一个JavaBean彻底能够转化为用xml这种描述性语言来表示,缘由是xml是指定好了协议,你的Java要变成 xml 就要按照个人协议来办事,用 xml 描述一个学生对象以下:

xml 表示的Java对象
xml 表示的Java对象

协议的话其实就很能理解,你的class是一个十六进制文件,那么就必须制定本身的协议啊,使得你的十六进制描述的东西能够转化为 JVM 能够理解的虚拟机指令,也就是你的 “xx” 这几个字母是为了告诉虚拟机干啥,“oo”这几个字母是想告诉虚拟机干啥,“xxoo”又是表示啥,这里先看看实际的JVM指令以及和class文件对应关系(如今的 JVM 指令有255个大约)

JVM指令表
JVM指令表

转化:有了思路就好办了,转化一下,将 JAVA 源码转化为 CLASS 文件,来看看具体怎么转化:

  1. 一个Java类对应一个class文件(有多是多个,若是类里面有内部类),里面有哪些东西?确定不能丢东西嘛,这是最基本的要求,若是人家明明写的是“你绿了我吗”,你给搞成了“你绿了我”,那这心情起伏仍是蛮大的哈。
  2. Java类里面的东西你怎么剖析,怎么设计存储?
  • 简单解剖一下,class文件多是Java中的class类,也多是接口,一个class所表示的里面还可能不止一个类和接口,得区分一下吧? 来,敲黑板划重点,大胆设计就是接口类型集合,普通类集合,还不止一个?再加两个字段接口个数,类个数,一切都是这么的完美,往class文件里面找,我去都能找到,OK,我是天才,下一个。
  • Java里面有属性,有方法,有常量,有字段,怎么破? 继续嘛,集合搞起来,个数存起来,最终获得了上面图里面的表结构的class文件。

再来回顾一下class文件内容: class文件对应内容

  1. Java类里面有什么东西,class文件应该存储些什么东西?
  • 两种数据类型:无符号数和表 无符号数属于基本数据类型(Java类中也有基本数据类型),以 u1,u2,u4,u8这种来表明1个字节,2个字节,4个字节,8个字节的无符号数,能够用来描述数字,索引引用,数量值或者字符串值。 就跟Java类中的对象引用类型同样,对象属性能够是基本数据类型(对应U1,U2无符号数),也能够是其余的对象(对应其余的表),Java工程项目中参数实体一般以"_Param"结尾(class文件的表都习惯以“_info”结尾)
  • 上图中的顺序,就是Class文件严格要求的顺序
  • 各个计数器主要是用来描述表里面数据个数,例如方法计数器的值是methods_count,表明方法表method——info里面有“methods_count”个方法
  • 整理一下,表结构用C语言表示相似下面的伪代码(忽略idea报错的红线)
class文件代码表示
class文件代码表示

完结撒花了?这里我是从宏观上讲解了下.class文件,下期进行.class类文件结构详细解析,以及字节码指令的剖析,本篇只是个开胃菜,下一篇内容才是主菜。 另外Java类在JVM里面的生命周期能够看我公众号上一篇内容

相关文章
相关标签/搜索