关于Java虚拟机.pdf
《关于Java虚拟机.pdf》由会员分享,可在线阅读,更多相关《关于Java虚拟机.pdf(13页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、一、什么是 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 虚拟机都由一个类加载器子系统(classloadersubsystem),负责加载程序中的类型(类和接口),并赋予唯一的名字。每一个Java 虚拟机都有一个执行引擎(executionengine)负责执行被加载类中包含的指令。程序的执行需要一定的内存空间,如字节码、被加载类的其他额外信息、程序中的对象、方法的参数、返回值、本地变量、处理的中间变量等等。Java 虚拟机将 这些信息统统保存在数据区(data areas)中。虽然每个 Java 虚拟机的实现中都包含数据
4、区,但是Java 虚拟机规范对数据区的规定却非常的抽象。许多结构上的细节部分都留给了Java 虚拟机实现者自己发挥。不同Java 虚拟机实现上的内存结构千差万别。一部分实现可能占用很多内存,而其他以下可能只占用很少的内存;一些实现可能会使用虚拟内存,而其他的则不使用。这种比较精炼的 Java 虚拟机内存规约,可以使得 Java 虚拟机可以在广泛的平台上被实现。数据区中的一部分是整个程序共有,其他部分被单独的线程控制。每一个Java 虚拟机都包含方法区(method area)和堆(heap),他们都被整个程序共享。Java 虚拟机加载并解析一个类以后,将从类文件中解析出来的信息保存与方法区中。
5、程序执行时创建的对象都保存在堆中。当一个线程被创建时,会被分配只属于他自己的PC寄存器“pc register”(程序计数器)和Java 堆栈(Java stack)。当线程不掉用本地方法时,PC寄存器中保存线程执行的下一条指令。Java 堆栈保存了一个线程调用方法时的状态,包括本地变量、调用方法的参数、返回值、处理的中间变量。调用本地方法时的状态保存在本地方法堆栈中(nativemethod stacks),可能再寄存器或者其他非平台独立的内存中。Java 堆栈有堆栈块(stackframes(or frames)组成。堆栈块包含 Java方法调用的状态。当一个线程调用一个方法时,Java
6、虚拟机会将一个新的块压到 Java 堆栈中,当这个方法运行结束时,Java 虚拟机会将对应的块弹出并抛弃。Java 虚拟机不使用寄存器保存计算的中间结果,而是用Java 堆栈在存放中间结果。这是的 Java 虚拟机的指令更紧凑,也更容易在一个没有寄存器的设备上实现 Java 虚拟机。图中的 Java 堆栈中向下增长的,PC寄存器中线程三为灰色,是因为它正在执行本地方法,他的下一条执行指令不保存在PC寄存器中。四、数据类型(Data Types)所有 Java 虚拟机中使用的数据都有确定的数据类型,数据类型和操作都在Java 虚拟机规范中严格定义。Java 中的数据类型分为原始数据类型(prim
7、itivetypes)和引用数据类型(referencetype)。引用类型依赖于实际的对象,但不是对象本身。原始数据类型不依赖于任何东西,他们就是本身表示的数据。所有 Java 程序语言中的原始数据类型,都是 Java 虚拟机的原始数据类型,除了布尔型(boolean)。当编译器将Java 源代码编译为自己码时,使用整型(int)或者字节型(byte)去表示布尔型。在Java 虚拟机中使用整数0 表示布尔型的 false,使用非零整数表示布尔型的true,布尔数组被表示为字节数组,虽然他 们可能会以字节数组或者字节块(bitfields)保存在堆中。除了布尔型,其他Java 语言中的原始类型
8、都是Java 虚拟机中的数据类型。在 Java 中数据类型被分为:整形的byte,short,int,long;char 和浮点型的float,double.Java 语言中的数据类型在任何主机上都有同样的范围。本页已使用福昕阅读器进行编辑。福昕软件(),版权所有,仅供试用。在Java 虚拟机中还存在一个Java 语言中不能使用的原始数据类型返回值类型(returnValue)。这种类型被用来实现Java 程序中的“finallyclauses”,具体的参见 18 章的“FinallyClauses”。引用类型可能被创建为:类类型(classtype),接口类型(interfacetype),
9、数组类型(arraytype)。他们都引用被动态创建的对象。当引用类型引用 null时,说明没有引用任何对象。Java 虚拟机规范只定义了每一种数据类型表示的范围,没有定义在存储时每种类型占用的空间。他们如何存储由Java 虚拟机的实现者自己决定。关于浮点型更多信息参见14 章“FloatingPointArithmetic”。五、字节长度Java 虚拟机中最小的数据单元式字(word),其大小由 Java 虚拟机的实现者定义。但是一个字的大小必须足够容纳byte,short,int,char,float,returnValue,reference;两个字必须足够容纳long,double.所
10、以虚拟机的实现者至少提供的字不能小于 31bits的字,但是最好选择特定平台上最有效率的字长。在运行时,Java 程序不能决定所运行机器的字长。字长也不会影响程序的行为,他只是在 Java 虚拟机中的一种表现方式。六、类加载器子系统Java 虚拟机中的类加载器分为两种:原始类加载器(primordialclassloader)和类加载器对象(classloaderobjects)。原始类加载器是Java 虚拟机实现的一部分,类加载器对象是运行中的程序的一部分。不同类加载器加载的类被不同的命名空间所分割。TypeRangebyte8-bitsignedtwoscomplement integer
11、(-27to 27-1,inclusive)short16-bitsigned twoscomplement integer(-215to 215-1,inclusive)int32-bitsignedtwoscomplement integer(-231to 231-1,inclusive)long64-bitsignedtwoscomplement integer(-263to 263-1,inclusive)char16-bitunsigned Unicode character(0 to 216-1,inclusive)float32-bitIEEE 754 single-precis
12、ionfloatdouble64-bitIEEE 754 double-precisionfloatreturnValueaddressof an opcode withinthe same methodreferencereferenceto an objecton the heap,or null本页已使用福昕阅读器进行编辑。福昕软件(),版权所有,仅供试用。类加载器调用了许多 Java 虚拟机中其他的部分和java.lang包中的很多类。比如,类加载对象就是java.lang.ClassLoader子类 的实例,ClassLoader 类中的方法可以访问虚拟机中的类加载机制;每一个被Ja
13、va 虚拟机加载的类都会被表示为一个java.lang.Class类的实例。像其他对象一样,类加载器对象和Class 对象都保存在堆中,被加载的信息被保存在方法区中。1、加载、连接、初始化(Loading,Linkingand Initialization)类加载子系统不仅仅负责定位并加载类文件,他按照以下严格的步骤作了很多其他的事情:(具体的信息参见第七章的“类的生命周期”)1)、加载:寻找并导入指定类型(类和接口)的二进制信息2)、连接:进行验证、准备和解析验证:确保导入类型的正确性准备:为类型分配内存并初始化为默认值解析:将字符引用解析为直接饮用3)、初始化:调用Java 代码,初始化类
14、变量为合适的值2、原始类加载器(The PrimordialClass Loader)每个 Java 虚拟机都必须实现一个原始类加载器,他能够加载那些遵守类文件格式并且被信任的类。但是,Java虚拟机的规范并没有定义如何加载类,这由 Java 虚拟机实现者自己决定。对于给定类型名的类型,原始莱加载器必须找到那个类型名加“。class”的文件并加载入虚拟机中。3、类加载器对象虽然类加载器对象是Java 程序的一部分,但是ClassLoader 类中的三个方法可以访问 Java 虚拟机中的类加载子系统。1)、protectedfinalClass defineClass():使用这个方法可以出入一
15、个字节数组,定义一个新的类型。2)、protectedClass findSystemClass(Stringname):加载指定的类,如果已经加载,就直接返回。3)、protectedfinalvoidresolveClass(Class c):defineClass()方法只是加载一个类,这个方法负责后续的动态连接和初始化。具体的信息,参见第八章“连接模型”(The LinkingModel)。本页已使用福昕阅读器进行编辑。福昕软件(),版权所有,仅供试用。4、命名空间当多个类加载器加载了同一个类时,为了保证他们名字的唯一性,需要在类名前加上加载该类的类加载器的标识。具体的信息,参见第八章
16、“连接模型”(The LinkingModel)。七、方法区(The Method Area)在 Java 虚拟机中,被加载类型的信息都保存在方法区中。这写信息在内存中的组织形式由虚拟机的实现者定义,比如,虚拟机工作在一个“little-endian”的处理器上,他就可以将信息保存为“little-endian”格式的,虽然在 Java 类文件中他们是以“big-endian”格式保存的。设计者可以用最适合并地机器的表示格式来存储数据,以保证程序能够以最快的速度执行。但是,在一个只有很小内存的设备上,虚拟机的实现者就不会占用很大的内存。程序中的所有线程共享一个方法区,所以访问方法区信息的方法必
17、须是线程安全的。如果你有两个线程都去加载一个叫Lava 的类,那只能由一个线程被容许去加载这个类,另一个必须等待。在程序运行时,方法区的大小是可变的,程序在运行时可以扩展。有些 Java虚拟机的实现也可以通过参数也订制方法区的初始大小,最小值和最大值。方法区也可以被垃圾收集。因为程序中的内由类加载器动态加载,所有类可能变成没有被引用(unreferenced)的状态。当类变成这种状态时,他就可 能被垃圾收集掉。没有加载的类包括两种状态,一种是真正的没有加载,另一个种是“unreferenced”的状态。详细信息参见第七章的类的生命周期(TheLifetimeof a Class)。1、类型信息
18、(Type Information)每一个被加载的类型,在Java 虚拟机中都会在方法区中保存如下信息:1)、类型的全名(The fullyqualifiednameof the type)2)、类型的父类型的全名(除非没有父类型,或者弗雷形式java.lang.Object)(The fullyqualifiednameof the type s directsuperclass)3)、给类型是一个类还是接口(classor an interface)(Whether or notthe type isa class)4)、类型的修饰符(public,private,protected,st
19、atic,final,volatile,transient等)(The type s modifiers)本页已使用福昕阅读器进行编辑。福昕软件(),版权所有,仅供试用。5)、所有父接口全名的列表(An orderedlistof the fullyqualifiednames of any directsuperinterfaces)类型全名保存的数据结构由虚拟机实现者定义。除此之外,Java 虚拟机还要为每个类型保存如下信息:1)、类型的常量池(The constantpool forthe type)2)、类型字段的信息(Fieldinformation)3)、类型方法的信息(Metho
20、d information)4)、所有的静态类变量(非常量)信息(Allclass(static)variablesdeclaredinthe type,exceptconstants)5)、一个指向类加载器的引用(Areferenceto classClassLoader)6)、一个指向 Class 类的引用(Areferenceto classClass)1)、类型的常量池(The constantpool forthe type)常量池中保存中所有类型是用的有序的常量集合,包含直接常量(literals)如字符串、整数、浮点数的常量,和对类型、字段、方法的符号引用。常量池 中每一个保存的
21、常量都有一个索引,就像数组中的字段一样。因为常量池中保存中所有类型使用到的类型、字段、方法的字符引用,所以它也是动态连接的主要对象。详细信息参见第六章“The Java Class File”。2)、类型字段的信息(Fieldinformation)字段名、字段类型、字段的修饰符(public,private,protected,static,final,volatile,transient等)、字段在类中定义的顺序。3)、类型方法的信息(Method information)方法名、方法的返回值类型(或者是void)、方法参数的个数、类型和他们的顺序、字段的修饰符(public,privat
22、e,protected,static,final,volatile,transient等)、方法在类中定义的顺序如果不是抽象和本地本法还需要保存方法的字节码、方法的操作数堆栈的大小和本地变量区的大小(稍候有详细信息)、异常列表(详细信息参见第十七章“Exceptions”。)4)、类(静态)变量(Class Variables)类变量被所有类的实例共享,即使不通过类的实例也可以访问。这些变量绑定在类上(而不是类的实例上),所以他们是类的逻辑数据的一部分。在Java虚拟机使用这个类之前就需要为类变量(non-final)分配内存本页已使用福昕阅读器进行编辑。福昕软件(),版权所有,仅供试用。常量
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 关于 Java 虚拟机
限制150内