什么是JVM?
JVM是Java virtual machine,中文译名为:JAVA虚拟机,是一个运行在计算机上的程序,职责是运行Java字节码文件。
Java与C/C++语言的不同
一般来说,JAVA语言不做任何优化的话,性能是不如C/C++的。因为JAVA语言对字节码指令实时解释成机器码在计算机中执行,而C/C++对源代码进行编译之后可以直接生成机器码文件。
那Java为什么这样做呢?主要是为了JAVA能够跨平台。
Java虚拟机的组成
首先,Java虚拟机通过类加载器把字节码文件加载到内存中,Java虚拟机就需要准备一个空间来存储这些内容。
如果创建对象,则需要开辟新的存储位置给该对象,开辟的存储位置叫做运行时数据区域。负责管理JVM用到的内存,例如创建对象和销毁对象。
字节码文件加载到内存后,JVM通过执行引擎把字节码文件中的指令解释称机器码,同时使即时编译器优化性能。
一些虚拟机使用C/C++进行编写,例如HotSpot,在运行时会调用一些在底层写好的C/C++方法,它们不存在于我们的目标字节码文件中,这些方法叫做本地接口。执行引擎负责执行本地接口的方法,而本地接口方法中创建的对象在运行时数据区域。
字节码文件的组成
字节码文件分为五部分
基础信息
包含魔数,字节码文件对应的Java版本号,访问标识,父类和接口
魔数是隐含的,主要是识别字节码文件的类型(若系统单纯使用文件后缀名识别文件,遇到后缀名与文件类型不同的情况会发生错误),例如,Java字节码文件的魔数是:cafebabe
主副版本号:jdk1.0使用了45.0,jdk1.1使用了45.3,jdk1.2使用的是46,之后每个jdk大版本就+1,所以我们1.2后,版本号计算为:主版本号-44.为了判断当前字节码文件版本与jdk版本是否匹配。
例如:
常量池
保存字符串常量,类或接口名,字段名,主要在字节码指令中使用。
字段
类或接口声明的字段信息
方法
当前类或接口声明的方法信息转换成字节码指令
属性
类的属性,源码的文件名,内部类的列表等
常量池
作用:为了避免相同的内容重复定义,节省空间。
例如,A1,A2都是String,且值都是“北京”,则A1,A2的常量池索引都是一样的,都是String类型的info。下面为A1的常量池信息
从上面我们获取到以下信息:一个属性的常量池信息,由属性名索引,常量池索引组成。系统通过寻找该属性的常量池索引,找到字符串字面量的索引,最终找到字面量。
为什么常量池要先找常量池索引,再找字符串字面量呢?
Java有字符串常量池,我们需要把该字节码文件的String类型加载进去,进行这样的操作可以保障起码有一个String能存进Java字符串常量池。
为什么不直接存String呢?非要一个属性需要存一个String,一个UTF-8?
假如我们拥有一个名字和值都一样的属性
常量池直接存String的话,我们发现,另外的字段名(name)abc就需要多存一份。如果存一个String索引,一个UTF-8索引的话,我们就可以发现,属性的name是可以直接引用UTF-8的索引来存储名字来达到节省空间的目的的。