2022年深入理解Java虚拟机 .pdf
《2022年深入理解Java虚拟机 .pdf》由会员分享,可在线阅读,更多相关《2022年深入理解Java虚拟机 .pdf(10页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、深入理解Java虚拟机( JVM)一、什么是Java虚拟机当你谈到Java虚拟机时,你可能是指:1、抽象的Java虚拟机规范2、一个具体的Java虚拟机实现3、一个运行的Java虚拟机实例二、 Java虚拟机的生命周期一个运行中的Java虚拟机有着一个清晰的任务:执行 Java程序。程序开始执行时他才运行,程序结束时他就停止。你在同一台机器上运行三个程序,就会有三个运行中的Java虚拟机。Java虚拟机总是开始于一个main()方法,这个方法必须是公有、返回void、直接受一个字符串数组。在程序执行时,你必须给Java虚拟机指明这个包换main()方法的类名。Main() 方法是程序的起点,他
2、被执行的线程初始化为程序的初始线程。程序中其他的线程都由他来启动。 Java中的线程分为两种: 守护线程 (daemon) 和普通线程( non-daemon ) 。守护线程是Java 虚拟机自己使用的线程,比如负责垃圾收集的线程就是一个守护线程。当然,你也可以把自己的程序设置为守护线程。包含Main()方法的初始线程不是守护线程。只要 Java虚拟机中还有普通的线程在执行,Java虚拟机就不会停止。如果有足够的权限,你可以调用exit()方法终止程序。三、 Java虚拟机的体系结构在 Java虚拟机的规范中定义了一系列的子系统、内存区域、数据类型和使用指南。这些组件构成了Java虚拟机的内部
3、结构,他们不仅仅为Java虚拟机的实现提供了清晰的内部结构,更是严格规定了Java虚拟机实现的外部行为。每一个 Java虚拟机都由一个类加载器子系统(class loader subsystem ) ,负责加载程序中的类型 (类和接口) , 并赋予唯一的名字。每一个 Java虚拟机都有一个执行引擎(execution engine)负责执行被加载类中包含的指令。程序的执行需要一定的内存空间,如字节码、被加载类的其他额外信息、程序中的对象、方法的参数、返回值、本地变量、处理的中间变量等等。Java 虚拟机将这些信息统统保存在数据区(data areas)中。虽然每个Java虚拟机的实现中都包含数
4、据区,但是Java虚拟机规范对数据区的规定却非常的抽象。许多结构上的细节部分都留给了Java虚拟机实现者自己发挥。 不同 Java虚拟机实现上的内存结构千差万别。一部分实现可能占用很多内存,而其他以下可能只占用很少的内存;一些实现可能会使用虚拟内存,而其他的则不使用。这种比较精炼的Java虚拟机内存规约,可以使得Java虚拟机可以在广泛的平台上被实现。数据区中的一部分是整个程序共有,其他部分被单独的线程控制。每一个Java虚拟机名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 1 页,
5、共 10 页 - - - - - - - - - 都包含方法区(method area )和堆( heap) ,他们都被整个程序共享。Java虚拟机加载并解析一个类以后,将从类文件中解析出来的信息保存与方法区中。程序执行时创建的对象都保存在堆中。当一个线程被创建时,会被分配只属于他自己的PC寄存器 “ pc register”(程序计数器)和 Java堆栈(Java stack) 。当线程不掉用本地方法时,PC寄存器中保存线程执行的下一条指令。 Java堆栈保存了一个线程调用方法时的状态,包括本地变量、调用方法的参数、返回值、处理的中间变量。 调用本地方法时的状态保存在本地方法堆栈中(nati
6、ve method stacks ) ,可能再寄存器或者其他非平台独立的内存中。Java堆栈有堆栈块 (stack frames (or frames) ) 组成。堆栈块包含Java方法调用的状态。当一个线程调用一个方法时,Java 虚拟机会将一个新的块压到Java堆栈中,当这个方法运行结束时, Java虚拟机会将对应的块弹出并抛弃。Java虚拟机不使用寄存器保存计算的中间结果,而是用Java堆栈在存放中间结果。这是的 Java虚拟机的指令更紧凑,也更容易在一个没有寄存器的设备上实现Java虚拟机。图中的 Java堆栈中向下增长的,PC寄存器中线程三为灰色,是因为它正在执行本地方法,他的下一条
7、执行指令不保存在PC寄存器中。四、数据类型(Data Types)所有 Java虚拟机中使用的数据都有确定的数据类型,数据类型和操作都在Java虚拟机规范中严格定义。Java中的数据类型分为原始数据类型( primitive types )和引用数据类型(reference type) 。引用类型依赖于实际的对象,但不是对象本身。原始数据类型不依赖于任何东西,他们就是本身表示的数据。所有Java 程序语言中的原始数据类型,都是Java 虚拟机的原始数据类型,除了布尔型(boolean ) 。当编译器将Java源代码编译为自己码时,使用整型 (int)或者字节型(byte)去表示布尔型。在Jav
8、a虚拟机中使用整数0 表示布尔型的false,使用非零整数表示布尔型的 true ,布尔数组被表示为字节数组,虽然他们可能会以字节数组或者字节块(bit fields )保存在堆中。除了布尔型,其他Java语言中的原始类型都是Java虚拟机中的数据类型。在Java 中数据类型被分为:整形的byte,short ,int,long;char 和浮点型的float,double。Java语言中的数据类型在任何主机上都有同样的范围。在Java 虚拟机中还存在一个Java 语言中不能使用的原始数据类型返回值类型(returnValue ) 。这种类型被用来实现Java程序中的“ finally cla
9、uses” ,具体的参见18 章的“Finally Clauses” 。引用类型可能被创建为:类类型(class type) ,接口类型(interface type) ,数组类型(array type ) 。他们都引用被动态创建的对象。当引用类型引用null 时,说明没有引用任何对象。Java虚拟机规范只定义了每一种数据类型表示的范围,没有定义在存储时每种类型占用的空间。他们如何存储由Java虚拟机的实现者自己决定。关于浮点型更多信息参见14 章“Floating Point Arithmetic ” 。TypeRange byte8-bit signed twos complement i
10、nteger (-27 to 27 - 1, inclusive) 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 2 页,共 10 页 - - - - - - - - - short16-bit signed twos complement integer (-215 to 215 - 1, inclusive) int32-bit signed twos complement integer (-231 to 231 - 1, inclusive) long64-bit sign
11、ed twos complement integer (-263 to 263 - 1, inclusive) char16-bit unsigned Unicode character (0 to 216 - 1, inclusive) float32-bit IEEE 754 single-precision float double64-bit IEEE 754 double-precision float returnValueaddress of an opcode within the same method referencereference to an object on t
12、he heap, or null 五、字节长度Java虚拟机中最小的数据单元式字(word) ,其大小由Java虚拟机的实现者定义。但是一个字的大小必须足够容纳byte,short ,int, char,float,returnValue ,reference;两个字必须足够容纳long, double。 所以虚拟机的实现者至少提供的字不能小于 31bits 的字,但是最好选择特定平台上最有效率的字长。在运行时, Java程序不能决定所运行机器的字长。字长也不会影响程序的行为,他只是在 Java虚拟机中的一种表现方式。六、类加载器子系统Java虚拟机中的类加载器分为两种:原始类加载器(prim
13、ordial class loader )和类加载器对象( class loader objects) 。原始类加载器是Java虚拟机实现的一部分,类加载器对象是运行中的程序的一部分。不同类加载器加载的类被不同的命名空间所分割。类加载器调用了许多Java虚拟机中其他的部分和java.lang 包中的很多类。比如,类加载对象就是java.lang.ClassLoader子类的实例, ClassLoader类中的方法可以访问虚拟机中的类加载机制;每一个被Java虚拟机加载的类都会被表示为一个java.lang.Class类的实例。 像其他对象一样, 类加载器对象和Class对象都保存在堆中, 被加
14、载的信息被保存在方法区中。1、加载、连接、初始化(Loading, Linking and Initialization )类加载子系统不仅仅负责定位并加载类文件,他按照以下严格的步骤作了很多其他的事情:(具体的信息参见第七章的“类的生命周期”)1) 、加载:寻找并导入指定类型(类和接口)的二进制信息2) 、连接:进行验证、准备和解析验证:确保导入类型的正确性准备:为类型分配内存并初始化为默认值解析:将字符引用解析为直接饮用3) 、初始化:调用Java代码,初始化类变量为合适的值2、原始类加载器(The Primordial Class Loader)每个 Java虚拟机都必须实现一个原始类加
15、载器,他能够加载那些遵守类文件格式并且被信任的类。但是,Java虚拟机的规范并没有定义如何加载类,这由Java 虚拟机实现者自己决定。对于给定类型名的类型,原始莱加载器必须找到那个类型名加“.class”的文件并加载入虚拟机中。3、类加载器对象虽然类加载器对象是Java 程序的一部分,但是ClassLoader类中的三个方法可以访问Java虚拟机中的类加载子系统。名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 3 页,共 10 页 - - - - - - - - - 1) 、prot
16、ected final Class defineClass(,):使用这个方法可以出入一个字节数组,定义一个新的类型。2) 、protected Class findSystemClass(String name): 加载指定的类, 如果已经加载,就直接返回。3) 、protected final void resolveClass(Class c) :defineClass()方法只是加载一个类,这个方法负责后续的动态连接和初始化。具体的信息,参见第八章“连接模型”( The Linking Model) 。4、命名空间当多个类加载器加载了同一个类时,为了保证他们名字的唯一性,需要在类名前加
17、上加载该类的类加载器的标识。具体的信息,参见第八章“连接模型”( The Linking Model ) 。七、方法区( The Method Area )在 Java虚拟机中,被加载类型的信息都保存在方法区中。这写信息在内存中的组织形式由虚拟机的实现者定义,比如,虚拟机工作在一个“little- endian”的处理器上,他就可以将信息保存为“little-endian ”格式的,虽然在Java类文件中他们是以“big-endian”格式保 存的。设计者可以用最适合并地机器的表示格式来存储数据,以保证程序能够以最快的速度执行。 但是,在一个只有很小内存的设备上,虚拟机的实现者就不会占用很大的
18、内存。程序中的所有线程共享一个方法区,所以访问方法区信息的方法必须是线程安全的。如果你有两个线程都去加载一个叫Lava 的类,那只能由一个线程被容许去加载这个类,另一个必须等待。在程序运行时,方法区的大小是可变的,程序在运行时可以扩展。有些Java虚拟机的实现也可以通过参数也订制方法区的初始大小,最小值和最大值。方法区也可以被垃圾收集。因为程序中的内由类加载器动态加载,所有类可能变成没有被引用( unreferenced )的状态。当类变成这种状态时,他就可能被垃圾收集掉。没有加载的类包括两种状态,一种是真正的没有加载,另一个种是“unreferenced ”的状态。详细信息参见第七章的类的生
19、命周期(The Lifetime of a Class) 。1、类型信息(Type Information )每一个被加载的类型,在Java虚拟机中都会在方法区中保存如下信息:1) 、类型的全名(The fully qualified name of the type )2) 、 类型的父类型的全名(除非没有父类型,或者弗雷形式java.lang.Object)(The fully qualified name of the type s direct superclass)3) 、给类型是一个类还是接口(class or an interface) ( Whether or not the
20、type is a class )4) 、类型的修饰符(public,private,protected ,static,final,volatile ,transient等) (The type s modifiers)5) 、所有父接口全名的列表(An ordered list of the fully qualified names of any direct superinterfaces )类型全名保存的数据结构由虚拟机实现者定义。除此之外, Java虚拟机还要为每个类型保存如下信息:1) 、类型的常量池(The constant pool for the type )2) 、类型字
21、段的信息(Field information )3) 、类型方法的信息(Method information )4) 、 所有的静态类变量 (非常量)信息 ( All class (static) variables declared in the type, 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 4 页,共 10 页 - - - - - - - - - except constants)5) 、一个指向类加载器的引用(A reference to class ClassL
22、oader)6) 、一个指向Class类的引用( A reference to class Class )1) 、类型的常量池(The constant pool for the type )常量池中保存中所有类型是用的有序的常量集合,包含直接常量(literals)如字符串、整数、浮点数的常量,和对类型、字段、方法的符号引用。常量池中每一个保存的常量都有一个索引,就像数组中的字段一样。因为常量池中保存中所有类型使用到的类型、字段、方法的字符引用,所以它也是动态连接的主要对象。详细信息参见第六章“The Java Class File ” 。2) 、类型字段的信息(Field informat
23、ion )字段名、字段类型、字段的修饰符(public, private,protected ,static,final ,volatile ,transient 等) 、字段在类中定义的顺序。3) 、类型方法的信息(Method information )方法名、方法的返回值类型(或者是void) 、方法参数的个数、类型和他们的顺序、字段的修饰符(public, private,protected ,static,final,volatile ,transient 等) 、方法在类中定义的顺序如果不是抽象和本地本法还需要保存方法的字节码、 方法的操作数堆栈的大小和本地变量区的大小(稍候有详细
24、信息) 、异常列表(详细信息参见第十七章“Exceptions” 。 )4) 、类(静态)变量(Class Variables )类变量被所有类的实例共享,即使不通过类的实例也可以访问。这些变量绑定在类上(而不是类的实例上),所以他们是类的逻辑数据的一部分。在Java虚拟机使用这个类之前就需要为类变量(non-final )分配内存常量( final)的处理方式于这种类变量(non-final )不一样。每一个类型在用到一个常量的时候, 都会复制一份到自己的常量池中。常量也像类变量一样保存在方法区中,只不过他保存在常量池中。 (可能是,类变量被所有实例共享,而常量池是每个实例独有的)。Non-
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 2022年深入理解Java虚拟机 2022 深入 理解 Java 虚拟机
限制150内