所谓虚拟机,就是一台虚拟的计算机。它是一款软件,用来执行一系列虚拟计算机指令。大体上,虚拟机可以分为系统虚拟机和程序虚拟机。大名鼎鼎的Visual Box、VMware就属于系统虚拟机,它们完全是对物理计算机的仿真,提供了一个可运行完整操作系统的软件平台。程序虚拟机的典型代表就是Java虚拟机,它专门为执行单个计算机程序而设计,在Java虚拟机中执行的指令我们称为Java字节码指令。无论是系统虚拟机还是程序虚拟机,在上面运行的软件都被限制于虚拟机提供的资源中。
通过Java虚拟机可以让Java程序实现跨平台的特性。如下图所示:
Java语言规范和Java虚拟机规范目前都可以在Oracle的官方网站上找到(http://docs.oracle.com/javase/specs/)。下面简要介绍一下Java语言规范。
Java语言规范是用来描述Java语言的,它定义了Java语言的语言特性,比如Java的语法词法、支持的数据类型、变量类型、数据类型转换的约定、数组、异常等内容。Java语言规范的目的是告诉开发人员“Java代码应该如何编写”。
每一种开发语言都会定义词法,语法,数据类型相关的规范,Java语言也是。
if Expression then
Statement
end if
但是在Java中给出了这样的定义:
IfThenStatement:
if Expression Statement
虽然Java语言和Java虚拟机有着密切的联系,但两者是完全不同的内容。Java虚拟机是一台执行Java字节码的虚拟计算机,它拥有独立的运行机制,其运行的Java字节码也未必由Java语言编译而成,像Groovy、Scala等语言生成的Java字节码也可以由Java虚拟机执行。立足于Java虚拟机,可以产生各种各样的跨平台语言。除了语言特性各不相同外,它们可以共享Java虚拟机带来的跨平台性、优秀的垃圾回收器,以及可靠的即时编译器。
因此,与Java语言不同,Java虚拟机是一个高效的、性能优异的、商用级别的软件运行和开发平台,而这也是我们学习的重点。
Java虚拟机规范的主要内容大概有以下几个部分:
以后的例题都是以JDK8来讲的,你可以在https://docs.oracle.com/javase/specs/jvms/se8/html/index.html浏览虚拟机规范全文。这份规范可以说是开发Java虚拟机的指导性文件,如果要实现自定义的Java虚拟机,则需要参考和熟悉这份规范,同时这份规范对于了解现存的流行Java虚拟机(如Hotspot、IBM J9等),也有十分重要的意义。
数字是计算机内最直接、最基础的表现类型。了解数字在计算机内的表示,对于了解整个
计算机系统具有相当重要的作用,数字也是专业计算机从业人员的基本功之一。下面我们主要介绍整数以及浮点数在Java虚拟机中的支持情况。
在Java虚拟机中,整数有byte、short、int、long四种,分别表示8位、16位、32位、64位有符号整数。整数在计算机中使用补码表示,在Java虚拟机中也不例外。在学习补码之前,必须先理解原码和反码。所谓原码,就是符号位加上数字的二进制表示。以int为例,第1位表示符号位(正数或者负数),其余31位表示该数字的二进制值。
10的原码为:00000000000000000000000000001010
-10的原码为:10000000000000000000000000001010
#对于原码来说,绝对值相同的正数和负数只有符号位不同。
反码就是在原码的基础上,符号位不变,其余位取反,以-10为例,其反码为:11111111111111111111111111110101
负数的补码就是反码加1,正数的补码就是原码本身。
Java中可以使用位运算符查看整数中每一位的实际值,方法如下:
int a = -10;
for (int i =0 ; i < 32;i++){
int t = (a&0x80000000>>>i)>>>(31-i);
System.out.print(t);
}//输出结果是:11111111111111111111111111110101
这段程序的基本思想是:进行32次循环(因为int有32位),每次循环取出int值中的位,第3行0x80000000是一个首位为1、其余位为0的数,通过右移i位,定位到要获取的第ⅰ位,并将除该位外的其他位统一设置为0,而该位不变,最后将该位移至最右,并进行输出。
为什么使用补码作为计算机内的实际存储方式而不是原码呢?
-- 计算-6+5的过程如下。
-6补码:11111010
5补码:00000101
直接相加得:11111111
-- 通过计算可知,11111111表示-1。
-- 计算4+6的过程如下。
4的补码:00000100
6的补码:00000110
直接相加得:00001010
-- 通过计算可知,00001010表示10(十进制)。
根据以上例子可以看到,使用补码表示时,只需要将补码简单地相加,即可得到算术加减法的正确结果,而无须区别正数或者负数。 在Java虚拟机中,浮点数有float和double两种,分别是32位和64位浮点数。浮点数在虚拟机中的表示比整数略显复杂。目前,使用最为广泛的是由IEEE754定义的浮点数格式。目前Java虚拟机中对于浮点数的处理参考IEEE754的规范。下面将以float为例,简要介绍浮点数的表示方法。
在IEEE754的定义中,一个浮点数由3部分组成,分别是:符号位、指数位和尾数位。以32位flot为例,符号位占1位,表示正负数,指数位占8位,尾数位占剩余的23位,如下图:
浮点数取值公式是:
举例说明,-5的表示为:1 1000 0001 010 0000 00000000 00000000
1 + 010 0000 00000000 00000000 = 1010 0000 00000000 00000000
套公式计算:
计算过程: