关于虚拟机!!

什么是虚拟机?

虚拟机的概念比较宽泛。通常人们接触到虚拟机的概念,包括像VMware这样的硬件仿真软件,以及像JVM这样介于硬件和编译器之间的软件。这里指的是后者。

虚拟机是一种抽象的计算机,它像实际的计算机一样,有一个指令集,并使用不同的存储区域。它负责执行指令和管理数据、内存和寄存器。这个虚拟机为任何平台上的编译器提供了一个公共接口。编译器只需要面对虚拟机,生成虚拟机能理解的代码,然后解释器把虚拟机代码转换成特定系统的机器码来执行。

java虚拟机

首先,什么是Java虚拟机

Java虚拟机是一种虚机,在实际计算机上通过软件模拟实现。Java虚拟机有自己想象的硬件,如处理器、堆栈、寄存器等。,并且也有相应的指令系统。

1.为什么要用Java虚拟机?

Java语言的一个非常重要的特点是它与平台无关。使用Java虚拟机是实现这一功能的关键。如果一个通用的高级语言要在不同的平台上运行,至少需要编译成不同的目标代码。引入Java虚拟机后,Java语言在不同平台上运行时不需要重新编译。Java语言使用模式Java虚拟机屏蔽了与特定平台相关的信息,使得Java语言编译器只需要生成运行在Java虚拟机上的目标代码(字节码),就可以在各种平台上运行,无需修改。Java虚拟机在执行字节码时,将字节码解释为特定平台上的机器指令执行。

2.谁需要了解Java虚拟机?

Java虚拟机是Java语言底层实现的基础,任何对Java语言感兴趣的人都应该对Java虚拟机有一个大致的了解。这有助于理解Java语言的一些属性并使用它。对于希望在特定平台上实现Java虚拟机的软件人员,Java语言的编译器作者,以及希望用硬件芯片实现Java虚拟机的人员,必须对Java虚拟机的规范有深入的了解。另外,如果你想扩展Java语言,或者把其他语言编译成Java语言的字节码,也需要对Java虚拟机有深入的了解。

3.Java虚拟机支持的数据类型。

Java虚拟机支持的Java语言的基本数据类型如下:

Byte://1字节的有符号整数的补码

short://2/双字节有符号整数的补码

int://4/4字节有符号整数的补码

long://8/8字节有符号整数的补码

Float://4字节IEEE754单精度浮点数

Double://8字节IEEE754双精度浮点数

Char://2字节无符号Unicode字符

几乎所有的Java类型检查都是在编译时完成的。上面列出的原始数据类型的数据在Java执行时不需要用硬件标记。操作这些原始数据类型的字节码(指令)已经指出了操作数的数据类型。比如iadd、ladd、fadd、dadd指令都是两个数相加,操作数类型是int、long、float、double。虚拟机不会为布尔类型设置单独的指令。布尔数据由整数指令处理,包括整数返回。布尔数组用字节数组处理。虚拟机使用IEEE754格式的浮点数。不支持IEEE格式的老电脑在运行Java数值计算程序时可能会非常慢。

虚拟机支持的其他数据类型包括:

Object//对Javaobject (object)的4字节引用

ReturnAddress//4字节,用于jsr/ret/jsr-w/ret-w指令。

注意:Java数组被视为对象。

虚拟机的规范对对象的内部结构没有特殊要求。在Sun公司的实现中,对对象的引用是一个句柄,它包含一对指针:一个指针指向对象的方法表,另一个指向对象的数据。Java虚拟机的字节码表示的程序应该符合类型规则。Java虚拟机的实现应该拒绝执行违反类型规定的字节码程序。由于字节码定义的限制,Java虚拟机似乎只能在32位地址空间的机器上运行。但是您可以创建一个Java虚拟机,自动将字节码转换成64位格式。从Java虚拟机支持的数据类型可以看出,Java严格规定了数据类型的内部格式,使得在各种Java虚拟机的实现中,对数据的解释是一致的,从而保证了Java的平台独立性和兼容性。

可移植性。

二、Java虚拟机架构

Java虚拟机由五部分组成:一组指令集、一组寄存器、一个堆栈、一个垃圾收集堆和一个方法区。这五个部分是Java虚拟机的逻辑组成部分,不依赖于任何实现技术或组织,但它们的功能必须以某种方式在真机上实现。

1.Java指令集

Java虚拟机支持大约248个字节码。每个字节码执行一个基本的CPU操作,比如向寄存器中添加一个整数,子例程转移等。Java指令集相当于Java程序的汇编语言。

Java指令集中的指令包含一个单字节运算符来指定要执行的操作,以及零个或多个操作数来提供操作所需的参数或数据。许多指令没有操作数,只包含一个单字节运算符。

虚拟机内部循环的执行过程如下:

做{

取一个操作符字节;

根据操作符的值执行操作;

}while(程序未完成)

由于指令系统的简单性,虚拟机执行的过程非常简单,有利于提高执行效率。指令中操作数的数量和大小由运算符决定。如果操作数大于一个字节,则它的存储顺序是高位字节优先。例如,16位参数在存储时占用两个字节,其值为:

第一个字节*256+第二个字节字节码指令流通常是字节对齐的。指令tabltch和lookup是例外,在这两个指令中需要强制的4字节边界对齐。

2.注册

Java虚拟机的寄存器用来保存机器的运行状态,类似于微处理器中的一些特殊寄存器。

Java虚拟机有四种寄存器:

Pc:Java程序计数器。

Optop:指向操作数堆栈顶部的指针。

Frame:指向当前执行方法的执行环境的指针。

Vars:指向当前正在执行的方法的局部变量区域中的第一个变量的指针。

java虚拟机

Java虚拟机是堆叠的。它不定义或使用寄存器来传递或接受参数。其目的是保证指令集的简单性和实现的效率(特别是对于寄存器数量较少的处理器)。

所有寄存器都是32位的。

3.堆

Java虚拟机的堆栈有三个区域:局部变量区、运行环境区和操作数区。

(1)局部变量区域每个Java方法都使用一个固定大小的局部变量集。它们根据vars寄存器的字偏移量进行寻址。局部变量都是32位的。长整数和双精度浮点数占用两个局部变量的空间,但根据第一个局部变量的索引寻址。(例如,如果一个索引为n的局部变量是一个双精度浮点数,它实际上占用了索引n和n+1所代表的存储空间。虚拟机规范不要求局部变量中的64位值是64位对齐的。虚拟机提供将局部变量中的值加载到操作数堆栈中的指令,并且还提供将操作数堆栈中的值写入局部变量中的指令。

(2)运行环境区包含的信息用于动态链接、正常方法返回和异常传播。

动态连接

运行时环境包括指向当前类和当前方法的解释器符号表的指针,以支持方法代码的动态链接。方法的类文件代码在引用要调用的方法和要访问的变量时使用符号。动态链接将符号方法调用翻译成实际的方法调用,加载必要的类来解释未定义的符号,并将变量访问翻译成这些变量运行时存储结构对应的偏移地址。动态链接方法和变量使得方法中使用的其他类的变化不会影响这个程序的代码。

正常方法返回

如果当前方法正常结束,当执行正确类型的返回指令时,被调用的方法将获得返回值。执行环境用于在调用者正常返回时恢复调用者的寄存器,并将调用者的程序计数器增加一个适当的值以跳过已执行的方法调用指令,然后在调用者的执行环境中继续执行。

异常和错误传播

Exception在Java中称为Error或exception,是Throwable类的子类。程序中的原因有:①动态链接错误,比如找不到需要的类文件。②运行时错误,如引用空指针。

程序使用throw语句。

当异常发生时,Java虚拟机采取以下措施:

检查与当前方法关联的catch子句表。每个catch子句都包含其有效的指令范围、可以处理的异常类型以及处理异常的代码块的地址。

与异常匹配的catch子句应满足以下条件:导致异常的指令在其指令范围内,并且发生的异常类型是其可以处理的异常类型的子类型。如果找到匹配的catch子句,系统移动到指定的异常处理块执行;如果没有找到异常处理块,则重复查找匹配catch子句的过程,直到检查完当前方法的所有嵌套catch子句。

由于虚拟机从第一个匹配的catch子句开始继续执行,catch子句表中的顺序非常重要。因为Java代码是结构化的,所以一个方法的所有异常处理程序总是可以按顺序排列在一个表中,对于任何可能的程序计数器值,都可以按线性顺序找到合适的异常处理块来处理程序计数器值下发生的异常。

如果找不到匹配的catch子句,则当前方法会得到一个“异常未被截获”的结果,并将其返回给当前方法的调用方,就好像异常刚刚发生在其调用方一样。如果在调用者中仍然没有找到相应的异常处理块,那么这个错误传播将继续。如果错误传播到顶层,系统将调用默认的异常处理块。

(3)操作数堆栈区的机器指令只从操作数堆栈中取出操作数,进行运算,并将结果返回堆栈。之所以选择堆栈结构,是因为它可以在只有少量寄存器或非通用寄存器的机器上(如Intel486)有效地模拟虚拟机的行为。操作数堆栈是32位。它用于向方法传递参数和从方法接收结果,还用于支持操作的参数和保存操作的结果。例如,iadd指令将两个整数相加。相加的两个整数应该是操作数堆栈顶部的两个字。这两个字是由前面的指令推到堆栈上的。这两个整数将弹出堆栈,相加,并将结果推回操作数堆栈。

每种原始数据类型都有特殊的指令来对它们执行必要的操作。每个操作数在堆栈中都需要一个存储位置,除了long和double类型,它们需要两个位置。操作数只能由适合其类型的运算符进行运算。例如,压入两个int类型的数字并将它们视为long类型的数字是非法的。在Sun的虚拟机实现中,这种限制是由字节码验证器强制执行的。然而,有一些操作(操作符dupe和swap)用于对运行时数据区进行操作,而不管其类型如何。

4.垃圾收集堆

Java的堆是一个运行时数据区,类的实例(对象)从这里分配空间。Java语言有收集无用单元的能力:它没有给程序员显式释放对象的能力。Java没有规定具体的垃圾收集算法,可以根据系统的要求使用各种算法。

5.方法区域

方法区域类似于传统语言中的编译代码或Unix进程中的主体段。它保存方法代码(编译的java代码)和符号表。在当前的Java实现中,方法代码不包含在垃圾收集堆中,但计划在未来的版本中实现。每个类文件都包含Java类或Java接口的编译代码。可以说,类文件就是Java语言的执行代码文件。为了保证类文件的平台无关性,Java虚拟机规范中也对类文件的格式进行了详细说明。具体可参考Sun的Java虚拟机规范。

受访者:笑看沧桑-举人四级12-15 22:27

-

你认为最好的答案是好的吗?目前有0条评论。

50% (0)

50% (0)

还有另外两个答案。

虚拟机的概念比较宽泛。通常人们接触到虚拟机的概念,包括像VMware这样的硬件仿真软件,以及像JVM这样介于硬件和编译器之间的软件。这里指的是后者。

虚拟机是一种抽象的计算机,它像实际的计算机一样,有一个指令集,并使用不同的存储区域。它负责执行指令和管理数据、内存和寄存器。这个虚拟机为任何平台上的编译器提供了一个公共接口。编译器只需要面对虚拟机,生成虚拟机能理解的代码,然后解释器把虚拟机代码转换成特定系统的机器码来执行。

java虚拟机

首先,什么是Java虚拟机

Java虚拟机是一种虚机,在实际计算机上通过软件模拟实现。Java虚拟机有自己想象的硬件,如处理器、堆栈、寄存器等。,并且也有相应的指令系统。

1.为什么要用Java虚拟机?

Java语言的一个非常重要的特点是它与平台无关。使用Java虚拟机是实现这一功能的关键。如果一个通用的高级语言要在不同的平台上运行,至少需要编译成不同的目标代码。引入Java虚拟机后,Java语言在不同平台上运行时不需要重新编译。Java语言使用模式Java虚拟机屏蔽了与特定平台相关的信息,使得Java语言编译器只需要生成运行在Java虚拟机上的目标代码(字节码),就可以在各种平台上运行,无需修改。Java虚拟机在执行字节码时,将字节码解释为特定平台上的机器指令执行。

2.谁需要了解Java虚拟机?

Java虚拟机是Java语言底层实现的基础,任何对Java语言感兴趣的人都应该对Java虚拟机有一个大致的了解。这有助于理解Java语言的一些属性并使用它。对于希望在特定平台上实现Java虚拟机的软件人员,Java语言的编译器作者,以及希望用硬件芯片实现Java虚拟机的人员,必须对Java虚拟机的规范有深入的了解。另外,如果你想扩展Java语言,或者把其他语言编译成Java语言的字节码,也需要对Java虚拟机有深入的了解。

3.Java虚拟机支持的数据类型。

Java虚拟机支持的Java语言的基本数据类型如下:

Byte://1字节的有符号整数的补码

short://2/双字节有符号整数的补码

int://4/4字节有符号整数的补码

long://8/8字节有符号整数的补码

Float://4字节IEEE754单精度浮点数

Double://8字节IEEE754双精度浮点数

Char://2字节无符号Unicode字符

几乎所有的Java类型检查都是在编译时完成的。上面列出的原始数据类型的数据在Java执行时不需要用硬件标记。操作这些原始数据类型的字节码(指令)已经指出了操作数的数据类型。比如iadd、ladd、fadd、dadd指令都是两个数相加,操作数类型是int、long、float、double。虚拟机不会为布尔类型设置单独的指令。布尔数据由整数指令处理,包括整数返回。布尔数组用字节数组处理。虚拟机使用IEEE754格式的浮点数。不支持IEEE格式的老电脑在运行Java数值计算程序时可能会非常慢。

虚拟机支持的其他数据类型包括:

Object//对Javaobject (object)的4字节引用

ReturnAddress//4字节,用于jsr/ret/jsr-w/ret-w指令。

注意:Java数组被视为对象。

虚拟机的规范对对象的内部结构没有特殊要求。在Sun公司的实现中,对对象的引用是一个句柄,它包含一对指针:一个指针指向对象的方法表,另一个指向对象的数据。Java虚拟机的字节码表示的程序应该符合类型规则。Java虚拟机的实现应该拒绝执行违反类型规定的字节码程序。由于字节码定义的限制,Java虚拟机似乎只能在32位地址空间的机器上运行。但是您可以创建一个Java虚拟机,自动将字节码转换成64位格式。从Java虚拟机支持的数据类型可以看出,Java严格规定了数据类型的内部格式,使得在各种Java虚拟机的实现中对数据的解释是一致的,从而保证了Java的平台独立性和兼容性。

可移植性。

二、Java虚拟机架构

Java虚拟机由五部分组成:一组指令集、一组寄存器、一个堆栈、一个垃圾收集堆和一个方法区。这五个部分是Java虚拟机的逻辑组成部分,不依赖于任何实现技术或组织,但它们的功能必须以某种方式在真机上实现。

1.Java指令集

Java虚拟机支持大约248个字节码。每个字节码执行一个基本的CPU操作,比如向寄存器中添加一个整数,子例程转移等。Java指令集相当于Java程序的汇编语言。

Java指令集中的指令包含一个单字节运算符来指定要执行的操作,以及零个或多个操作数来提供操作所需的参数或数据。许多指令没有操作数,只包含一个单字节运算符。

虚拟机内部循环的执行过程如下:

做{

取一个操作符字节;

根据操作符的值执行操作;

}while(程序未完成)

由于指令系统的简单性,虚拟机执行的过程非常简单,有利于提高执行效率。指令中操作数的数量和大小由运算符决定。如果操作数大于一个字节,则它的存储顺序是高位字节优先。例如,16位参数在存储时占用两个字节,其值为:

第一个字节*256+第二个字节字节码指令流通常是字节对齐的。指令tabltch和lookup是例外,在这两个指令中需要强制的4字节边界对齐。

2.注册

Java虚拟机的寄存器用来保存机器的运行状态,类似于微处理器中的一些特殊寄存器。

Java虚拟机有四种寄存器:

Pc:Java程序计数器。

Optop:指向操作数堆栈顶部的指针。

Frame:指向当前执行方法的执行环境的指针。

Vars:指向当前正在执行的方法的局部变量区域中的第一个变量的指针。

java虚拟机

Java虚拟机是堆叠的。它不定义或使用寄存器来传递或接受参数。其目的是保证指令集的简单性和实现的效率(特别是对于寄存器数量较少的处理器)。

所有寄存器都是32位的。

3.堆

Java虚拟机的堆栈有三个区域:局部变量区、运行环境区和操作数区。

(1)局部变量区域每个Java方法都使用一个固定大小的局部变量集。它们根据vars寄存器的字偏移量进行寻址。局部变量都是32位的。长整数和双精度浮点数占用两个局部变量的空间,但根据第一个局部变量的索引寻址。(例如,如果一个索引为n的局部变量是一个双精度浮点数,它实际上占用了索引n和n+1所代表的存储空间。虚拟机规范不要求局部变量中的64位值是64位对齐的。虚拟机提供将局部变量中的值加载到操作数堆栈中的指令,并且还提供将操作数堆栈中的值写入局部变量中的指令。

(2)运行环境区包含的信息用于动态链接、正常方法返回和异常传播。

动态连接

运行时环境包括指向当前类和当前方法的解释器符号表的指针,以支持方法代码的动态链接。方法的类文件代码在引用要调用的方法和要访问的变量时使用符号。动态链接将符号方法调用翻译成实际的方法调用,加载必要的类来解释未定义的符号,并将变量访问翻译成这些变量运行时存储结构对应的偏移地址。动态链接方法和变量使得方法中使用的其他类的变化不会影响这个程序的代码。

正常方法返回

如果当前方法正常结束,当执行正确类型的返回指令时,被调用的方法将获得返回值。执行环境用于在调用者正常返回时恢复调用者的寄存器,并将调用者的程序计数器增加一个适当的值以跳过已执行的方法调用指令,然后在调用者的执行环境中继续执行。

异常和错误传播

Exception在Java中称为Error或exception,是Throwable类的子类。程序中的原因有:①动态链接错误,比如找不到需要的类文件。②运行时错误,如引用空指针。

程序使用throw语句。

当异常发生时,Java虚拟机采取以下措施:

检查与当前方法关联的catch子句表。每个catch子句都包含其有效的指令范围、可以处理的异常类型以及处理异常的代码块的地址。

与异常匹配的catch子句应满足以下条件:导致异常的指令在其指令范围内,并且发生的异常类型是其可以处理的异常类型的子类型。如果找到匹配的catch子句,系统移动到指定的异常处理块执行;如果没有找到异常处理块,则重复查找匹配catch子句的过程,直到检查完当前方法的所有嵌套catch子句。

由于虚拟机从第一个匹配的catch子句开始继续执行,catch子句表中的顺序非常重要。因为Java代码是结构化的,所以一个方法的所有异常处理程序总是可以按顺序排列在一个表中,对于任何可能的程序计数器值,都可以按线性顺序找到合适的异常处理块来处理程序计数器值下发生的异常。

如果找不到匹配的catch子句,则当前方法会得到一个“异常未被截获”的结果,并将其返回给当前方法的调用方,就好像异常刚刚发生在其调用方一样。如果在调用者中仍然没有找到相应的异常处理块,那么这个错误传播将继续。如果错误传播到顶层,系统将调用默认的异常处理块。

(3)操作数堆栈区的机器指令只从操作数堆栈中取出操作数,进行运算,并将结果返回堆栈。之所以选择堆栈结构,是因为它可以在只有少量寄存器或非通用寄存器的机器上(如Intel486)有效地模拟虚拟机的行为。操作数堆栈是32位。它用于向方法传递参数和从方法接收结果,还用于支持操作的参数和保存操作的结果。例如,iadd指令将两个整数相加。相加的两个整数应该是操作数堆栈顶部的两个字。这两个字是由前面的指令推到堆栈上的。这两个整数将弹出堆栈,相加,并将结果推回操作数堆栈。

每种原始数据类型都有特殊的指令来对它们执行必要的操作。每个操作数在堆栈中都需要一个存储位置,除了long和double类型,它们需要两个位置。操作数只能由适合其类型的运算符进行运算。例如,压入两个int类型的数字并将它们视为long类型的数字是非法的。在Sun的虚拟机实现中,这种限制是由字节码验证器强制执行的。然而,有一些操作(操作符dupe和swap)用于对运行时数据区进行操作,而不管其类型如何。

4.垃圾收集堆

Java的堆是一个运行时数据区,类的实例(对象)从这里分配空间。Java语言有收集无用单元的能力:它没有给程序员显式释放对象的能力。Java没有规定具体的垃圾收集算法,可以根据系统的要求使用各种算法。

5.方法区域

方法区域类似于传统语言中的编译代码或Unix进程中的主体段。它保存方法代码(编译的java代码)和符号表。在当前的Java实现中,方法代码不包含在垃圾收集堆中,但计划在未来的版本中实现。每个类文件都包含Java类或Java接口的编译代码。可以说,类文件就是Java语言的执行代码文件。为了保证类文件的平台无关性,Java虚拟机规范中也对类文件的格式进行了详细说明。有关详细信息,请咨询Sun。