Java虚拟机(JVM)概述

JVM(Java虚拟机)是一个抽象的计算模型。就如同一台真实的机器,它有自己的指令集和执行引擎,可以在运行时操控内存区域。目的是为构建在其上运行的应用程序提供一个运行环境。JVM可以解读指令代码并与底层进行交互:包括操作系统平台和执行指令并管理资源的硬件体系结构。本文主要对JVM进行概述,并介绍Java程序是如何在上面执行的。

虚拟机

从本质上讲,虚拟机是个被构建来提供特定或通用目的服务环境的非实体计算机。这听起来像是一个仿真器,用来仿真机器未配置或不能按要求执行任务的硬件组件。因此,我们要做的就是创建一个软件,以软件的形式模拟硬件提供的服务,使之看起来这个特定的硬件在系统中是实际存在的。虚拟机在一定程度上使用CPU虚拟化,为实际的硬件问题提供一个接口。所以可以说它实际上有两种功能:提供一个虚拟的环境,或者将某些不存在的事物进行抽象化。但是当我们深入了解之后会发现,这两种功能有着很明显的不同。我们现在暂且不看它们之间的不同点,它们的共同点在于都“假装”成它们不是的东西。正如Popek和Goldberg在论文“Formal Requirements for Virtualizable Third Generation Architectures”里说的,它是“一个真实机器有效、独立的复制品。”

基于不同的需求和用途,虚拟机有很多类型。一种叫完全虚拟化(full virtualization),这种虚拟机表现得像一台真正的机器。其他类型的虚拟机会更精细,更专业,比如进程虚拟化(process virtualization)。而对JVM进行分类是很困难的,因为它对CPU进行了虚拟化,有自己的运行时环境、与底层平台协调工作的内存管理器、垃圾收集器,当然还有大量作为中间字节码输入的类库,最后但同样重要的是,它能够模拟机器的寄存器、堆栈等等。简单地说,它是被Java编译器编译为java的本质——字节码的游乐场。字节码实际上是JVM用来将代码重新翻译为本地机器指令所使用的机器代码。

类文件格式

有趣的是,其实JVM并不关心Java语言或其他编程语言的语义和语法结构。当JVM执行一段程序的时候,它主要关注的是一种称为“类文件”的特定文件格式。*.class类文件格式和Java代码定义的面向对象的类结构毫无关系。编译器将*.java文件编译成*.class文件,然后JVM对*.class文件进行解译,它不关心这个类文件是由哪种编译器生成的,只要符合类文件的文件格式即可。Java编译器将一段程序编译为等价的类文件。这些类文件实际上包含了半编译的代码——字节码。之所以称之为半编译,是因为字节码并不像C/C++编译器编译的二进制文件一样会被直接执行。字节码要先被输入到JVM中,然后再转换为底层平台可以执行的最终指令。所以字节码包含了JVM的指令、符号表和其他的辅助信息。不管何种语言,能根据JVM的语法和结构约束编译生成字节码的编译器,都是一个可以在JVM上执行的候选者。

JVM的定位

JVM将自身定位于字节码和底层平台之间。底层平台是指操作系统(OS)和硬件。操作系统和硬件体系结构在不同的机器上可能不同,但是同一段Java程序可以不用做任何的代码修改就能在不同的机器上运行。这是在虚拟环境中执行的程序语言的独特之处。例如,由其他程序语言编译器编译的目标代码如C++和Java相比的不同点在于,C++程序需要被特定平台的编译器重新编译,从而使它能在不同的体系结构上面运行。而Java代码并不需要做任何改变,因为由Java编译器编译的字节码是在外围的JVM上执行。因此,JVM负责重新解译由Java编译器生成的字节码,并和底层平台协调工作。也就是说,尽管Java编译器生成的结果是平台独立的,但JVM与特定平台相关的。除非两台机器有相同的体系结构,在某个体系结构上安装和使用的JVM可能换一台机器就不能正常工作了。

相对于JVM, JRE和JDK又是什么?

想要运行Java程序,我们需要JVM因为它提供了字节码的运行环境。Oracle提供了两种不同的产品:JDK(Java开发工具)和JRE(Java运行环境)。JRE是我们安装运行Java程序的最基本软件。它和Java类库以及运行Java程序所需要的其他组件一起够成了JVM的一个实现。所以,如果我们想运行一个类文件或一段字节码,仅需要JRE就够了。而JDK(Java开发工具)是JRE的超集。它包含了JRE提供的所有东西,包括创建类文件的工具如Java编译器、调试器和其他许多开发Java程序相关的工具。所以,当我们要创建类文件(编译Java源码)时,我们就需要JDK。下面是一张Java API文档的截图。注意组成JDK,JRE和Java SE API核心类库的组件;通过这张截图你可以了解JRE和JDK里面都有哪些内容。

Java提供了Java虚拟机规范来让我们对JVM的工作原理有一个完整的认识。你可以从这里得到概念性知识,并开发一个自己的JVM;但这并不是一个简单的工作。现在市场上已经有很多JVM了,其中有些是免费的,还有一些需要购买商业许可证才能使用。

在JVM上执行Java程序

每一个在JRE上运行的Java程序都会创建一个JVM实例。编译后的Java类文件和其他被依赖的类文件会被加载到运行环境中。这一步由类加载器协助完成。

类加载器通过三步完成类加载。

Firstly, it loads the program classes, along with standard Java classes that are bundled with JDK in the form of bytecode. The standard classes form the core API library of Java. The bootstrap begins by locating the core API libraries classes typically situated in jre/lib.

首先,类加载器会以字节码的形式加载程序类文件和与JDK绑定的标准Java类文件。标准类文件构成了Java API核心类库。引导程序通过定位通常位于jre/lib目录下的核心API类库启动。

然后,扩展机制定位扩展类库,例如一些为开发或执行代码而被添加到Java里新的(可选)包。扩展类通常位于 jre/lib/ext目录下。有时,扩展类会被放到系统属性java.ext.dirs 定义的其他目录下面。程序包使用JAR或ZIP的扩展名。

最后,如果要加载的类没有在Java的标准类库或扩展类库中被找到,加载器会搜索CLASSPATH环境变量下定义的文件路径,CLASSPATH里面包含了诸多存储类文件的地址。系统属性java.class.path对CLASSPATH环境变量做了映射。

像JAR或ZIP这样的归档文件都是包含了一些其他文件目录的独立文件,通常是压缩文件格式。例如,程序中使用的标准类库包含在归档文件 rt.jar中,该文件会和JDK被一同安装。

一旦文件被定位并加载之后,类加载器会执行不同的功能,例如根据JVM的约束进行校验、内存分配,或者在调用构造器设置定义的变量元素之前使用默认值初始化类变量。

当加载程序结束之后,字节码指令被传递给执行引擎。然后JVM借助于绑定到指定平台的特定JVM实现的本地代码和底层操作系统进行交互。请注意,不同平台的实现可能有略微不同。

数据存储区的堆空间用于存储动态或临时分配的内存空间。类和数组是在这块区域里创建的。当创建对象大小超出堆内存空间时,垃圾收集器会回收内存。

Java栈,又叫栈帧,用于存储局部变量和不同阶段方法调用的临时结果。每一次方法调用都会创建一个栈帧。

方法区基本上是JVM线程间的共享存储区。

寄存器是一个模拟的底层机器寄存器,主要用于执行字节码指令。PC寄存器或程序计数器是用于保存当前指令执行地址的主要寄存器。

JVM功能概述

JVM的功能可以归纳为:

  • 加载:通过类加载器加载类文件的过程。
  • 链接:链接类文件,提交给JVM在运行时执行。
  • 初始化:分配内存和调用类初始化方法设置变量值。

总结

使用虚拟机执行程序的最大好处是它是平台独立的。和C/C++这种高效的语言相比,这种类型编程语言的生产力可以弥补其性能上的弱点。本文仅仅是对JVM的一点浅见,但也许已经足以帮助理解JVM是如何实际工作的。

原文链接: developer 翻译: ImportNew.com辰午
译文链接: http://www.importnew.com/29224.html

原文地址:https://www.cnblogs.com/rinack/p/9748835.html

时间: 2024-08-29 18:41:32

Java虚拟机(JVM)概述的相关文章

Java虚拟机JVM简单理解

Java虚拟机JVM的作用: Java源文件(.java)通过编译器编译成.class文件,.class文件通过JVM中的解释器解释成特定机器上的机器代码,从而实现Java语言的跨平台. JVM的体系结构包含三个主要的子系统和一个内存区,分别是: 垃圾回收器:用于回收堆(heap)中无引用的对象. 类装载子系统:定位及导入二进制class文件,校验被导入类的正确性,为类变量分配初始化内存,以及帮助解析符号引用. 执行引擎:执行被转载类中的方法指令. 运行时数据区:又叫做虚拟机内存或Java内存.

《深入理解Java虚拟机 JVM高级特性...》核心笔记

深入理解Java虚拟机 JVM高级特性与最佳实践(第二版) 核心笔记 JAVA 环境: JAVA虚拟机高级特性: 一:java内存区域与内存异常 一):运行数据区     1:程序计数器(Program Counter Register),也称"PC寄存器" A:用来指示需要执行哪条指令的.(在汇编语言中,CPU在得到指令之后,程序计数器便自动加1或者根据                    转移指针得到下一条指令的地址,如此循环,直至执行完所有的指令.) B:由于在JVM中,多线程

java虚拟机--JVM

java虚拟机 是安装在计算机操作系统上的一个虚拟计算机. 专门用于处理java程序和底层操作系统的链接工作,将java程序翻译成底层的操作系统可以理解的语言. 有别于JDK.JDK是java的开发环境,是java开发人员需要的,里面除了JVM,还有一些其他的东西.JVM是小于JDK的. JVM的结构图如下图所示: 1. 类加载器:加载类文件到内存.[这里的类文件是class文件] 2. 运行数据区:1中加载的class文件,全部保存在运行数据区.java能够很好的运行,也是得益于运行数据区的管

Java虚拟机JVM学习04 类的初始化

Java虚拟机JVM学习04 类的初始化 类的初始化 在初始化阶段,Java虚拟机执行类的初始化语句,为类的静态变量赋予初始值. 在程序中,静态变量的初始化有两种途径: 1.在静态变量的声明处进行初始化: 2.在静态代码块中进行初始化. 没有经过显式初始化的静态变量将原有的值. 静态变量的声明语句,以及静态代码块都被看做类的初始化语句,Java虚拟机会按照初始化语句在类文件中的先后顺序来依次执行它们. 类的初始化步骤 1.假如这个类还没有被加载和连接,那就先进行加载和连接. 2.假如类存在直接的

Java虚拟机JVM学习05 类加载器的父委托机制

Java虚拟机JVM学习05 类加载器的父委托机制 类加载器 类加载器用来把类加载到Java虚拟机中. 类加载器的类型 有两种类型的类加载器: 1.JVM自带的加载器: 根类加载器(Bootstrap) 扩展类加载器(Extension) 系统类加载器(System) 2.用户自定义的类加载器: java.lang.ClassLoader的子类,用户可以定制类的加载方式. JVM自带的加载器 Java虚拟机自带了以下几种加载器. 1.根(Bootstrap)类加载器: 该加载器没有父加载器. 它

深入Java虚拟机JVM类加载初始化学习笔记

1. Classloader的作用,概括来说就是将编译后的class装载.加载到机器内存中,为了以后的程序的执行提供前提条件. 2. 一段程序引发的思考: 风中叶老师在他的视频中给了我们一段程序,号称是世界上所有的Java程序员都会犯的错误. 一般不假思索的结论就是,a=1,b=1.给出的原因是:a.b都是静态变量,在构造函数调用的时候已经对a和b都加1了.答案就都是1.但是运行完后答案却是a=1,b=0. 为什么呢,这3句无非就是静态变量的声明.初始化,值的变化和声明的顺序还有关系吗?Java

书籍推荐:《实战Java虚拟机——JVM故障诊断与性能优化》下载

本书详细介绍Java虚拟机的基本原理和优化诊断方法.其中重点介绍Java虚拟机的体系结构.常用的虚拟机参数.Java虚拟机的垃圾回收原理.算法以及目前虚拟机所支持的各种垃圾回收器及其区别.特点和使用方法.在实践和调优方面,重点介绍了Java的堆.栈分析方法,性能调优的一般思路.手段和工具.此外,还详细介绍了虚拟机内有关"锁"的实现以及优化方法. 作为对虚拟机的深入了解,本书还将详细介绍Java类的基本格式.装载过程和虚拟机的执行机制. Java虚拟机目前是Java.Scala.Cloj

java虚拟机jvm启动后java代码层面发生了什么?

java虚拟机jvm启动后java代码层面发生了什么? 0000 我想验证的事情 java代码在被编译后可以被jdk提供的java命令进行加载和运行, 在我们的程序被运行起来的时候,都发生了什么事情, 下面就来探究下这个问题, 这个问题被拆成了两个问题, 第一个问题用来确定发生了哪些事情, 第二个问题用来确定这些事情是如何进行的. java进程里面都发生了哪些活动? 这些活动在java代码(反编译或者是源码)级别有所体现吗? 0001 寻找验证的方式 当我在探究上面两个问题时, 我想了很多方式去

深入Java虚拟机——JVM内存详解

在C++中,程序员拥有每一个对象的所有权,但与此同时还肩负着释放对象内存空间的责任:而Java由于有了虚拟机的帮助,程序员拥有对象的所有权的同时不再需要释放对象的内存空间.由于是JVM自动进行对象内存的释放,所以内存泄漏和内存溢出的问题也很少出现. Java虚拟机在运行时将内存空间分成5个部分,分别是:方法区.虚拟机栈.本地方法栈.堆.程序计数器. 程序计数器 本质 程序计数器本质上是一块较小的内存空间. 作用 可以把程序计数器简单地看作是当前线程所执行的字节码的行号指示器. 字节码解释器在工作

JAVA虚拟机(JVM)以及跨平台原理(JDK、JRE、JVM)

相信大家已经了解到Java具有跨平台的特性,可以“一次编译,到处运行”,在Windows下编写的程序,无需任何修改就可以在Linux下运行,这是C和C++很难做到的. 那么,跨平台是怎样实现的呢?这就要谈及Java虚拟机(Java Virtual Machine,简称 JVM). JVM也是一个软件,不同的平台有不同的版本.我们编写的Java源码,编译后会生成一种 .class 文件,称为字节码文件.Java虚拟机就是负责将字节码文件翻译成特定平台下的机器码然后运行.也就是说,只要在不同平台上安