1.1 Java虚拟机的原理
所谓的虚拟机,就是一台虚拟的计算机。它是一款软件,用来执行一系列虚拟计算机指令。大体上,虚拟机可以分为系统虚拟机和程序虚拟机。大名鼎鼎的Visual Box、VMware就属于系统虚拟机,他们完全是对物理计算机的仿真。提供了一个可运行完整操作系统的软件平台。程序虚拟机的典型代表就是Java虚拟机,它专门为执行单个计算机而设计,在Java虚拟机中执行的指令被我们成为java字节码指令。无论是系统虚拟机还是程序虚拟机,在上面运行的软件都被限制于虚拟机的资源中。
1.2 Java虚拟机的种类
Java发展至今,先后出现了不少的Java虚拟机。在Java发展初期,sun使用的是一款叫作Classuc的Java虚拟机之后,在Solaris平台上还曾短暂地使用过Exact VM虚拟机,到现在,最终被大规模部署和应用的是Hotspot虚拟机。
除了Sun公司以外,各大公司以及组织都曾积极研发过Java虚拟机,比如BEA的JRockit,目前,JRrokit和Hospot都被收入Oralce旗下,大有整合的趋势,在IBM内部,使用这一款名为J9的虚拟机,广泛用于IBM的各大产品。此外,Apache也曾推出过1.5和JDK1.6兼容的Java运行平台Apache Harmony,它是开源软件,但受到同样开源的OpenJDK的压制,最终在2011年退役,虽然目前没有Apache Harmony被大规模商用的案例,但是他出现对Android的发展起到极为重要的的作用。在嵌入式领域,KVM和CDC/CLDC Hotspot两款虚拟机也扮演着重要的角色,子啊ios和Android盛行之前,这两款虚拟机也广泛运用于手机平台。
1.3 Java语言规范
讲到Java虚拟机,就不得不说Java,说到Java,就不得不提Java语言规范,Java语言规范和Java虚拟机规范都可以在Oracle的官方网站上找到(http://docs.oracle.com/javase/specs)。
Java语言规范是用来描述Java语言的,它定义了Java语言的语言特性,比如JAVA的语法、词法、支持的数据类型、变量类型、数据类型转换的约定、数组、异常等内容。Java语言规范的目的是开发人员"Java代码应该如何编写"。
1.3.1 词法的定义
词法规定了Java语法中每一个单词如何写才是合乎规范的。比如,词法定义中规定了Java的关键字,如果开发人员使用java的关键字作为变量名,无法正常通过编译。
1.3.2 语法的定义
词法定义规定了什么样的单词是合理的,语法定义规定了什么杨的语句是合乎规范的。
1.3.3 数据类型的定义
Java语言规范中还定义java的数据类型,根据java1.7的规范,Java的数据类型分为原始数据类型和引用数据类型。原始数据类型又分为数据型和布尔型。数字型又又byte、short、int、long、char、float、double.注意,在这里char被定义为整数型,并且在规范中明确定义:byte、short、int、long分别是8位、16位、32位、63位有符号整数,而char为无符号整数,表示UTF-16的字符。布尔型只有两种取值:true和false。而对float和double,规范中规定,他们是满足IEEE754的32位浮点数和64位浮点数。
此外,规范还定义了各类数字的取值范围、初始值,以及能够支持的各种操作。以整数为例,比较运算、数值运算、位运算、自增自减运算等都在规范中有描述。
除了基本数据类型外,引用数据类型也是Java重要的组成部分,引用数据类型分为3种:类或者接口、泛型类型以及数组类型。
1.4 Java虚拟机规范
1.定义了虚拟机的内部结构
2.定义了虚拟机执行的字节码类型和功能。
3.定义了class文件的结构。
4.定义了类的装载、连接和初始化
1.5 数字编码
1.5.1整数在java整数在java虚拟机中的表示
在java虚拟机中,整数byte、short、int、long四种,分别表示8位、16位、32位、64位有符号整数。整数在计算机中使用补码表示,在学习补码之前,必须理解原码和反码。
所谓原码,就是符号位加上数字的二进制表示。以int为例,第一位表示符号位,其余32位表示该数字的二进制值。
对于原码来说,绝对值相同的整数和负数只有符号位不同。
反码就是在原码的基础上,符号位不同,其余位取反,以-10为例,其反码为:11111111 11111111 11111111 11110101
负数的反码就是补码加1,整数的补码就是原码本身。
因此,10的补码为:00000000 0000000 00000000 00000101 而-10的补码为11111111 11111111 11111111 11110110
相对于原码,使用补码作为计算机内的实际存储方式至少有连个好处。
(1)可以统一数字0的表示。由于0即非正数,又非负数,使用原码表示时符号位难以确定,把0归入整数或负数的到原码编码时不同的。但是使用补码表示时,无论把0归入正数或者负数都会得到相同的结果。
(2)使用补码可以简化整数的加减法计算,将减法计算视为加法计算,实现减法和加法的完全统一,实现正数和负数加法的统一。
1.5.2 浮点数在Java虚拟机中的表示
在Java虚拟机中,浮点数有float和double两种,分别是32位和64位浮点数。浮点数在虚拟机中的表述比整数略显复杂。目前使用最为广泛的是由IEEE754定义的浮点数格式。
1.6 编译和调试虚拟机
如果要对虚拟机进行深入研究,那么编译和调试Java虚拟机是必不可少的。为何要编译自己的虚拟机呢?主要原因由两点。
第一,通过自己编译可以得到一个debug或者fastdebug版本的调试虚拟机。调试用虚拟机可以支持更多的虚拟机参数,这些开发专用的虚拟机参数可以帮助开发人员获得更多的虚拟机内部信息,而这些参数在正常发行版本中是无法使用的。
第二,使用自己编译的调试版的虚拟机可以用于虚拟机的但不调试,有利于实现对虚拟机代码的理解。由于虚拟机代码比较复杂,仅通过代码阅读很难深入理解其实现机制,有时不得不依靠单步调试进行辅助,而编译后调试版本可以帮助实现这一功能。