当前位置:文档之家› Java虚拟机工作原理(JVM)

Java虚拟机工作原理(JVM)

As the Java Virtual Machine is a stack-based machine, almost all of its instructions involve the operand stack in some way. Most instructions push values, pop values, or both as they perform their functions.Java虚拟机是基于栈的(stack-based machine)。

几乎所有的java虚拟机的指令,都与操作数栈(operand stack)有关.绝大多数指令都会在执行自己功能的时候进行入栈、出栈操作。

1Java体系结构介绍Javaís architecture arises out of four distinct but interrelated technologies, each of which is defined by a separate specification from Sun Microsystems:1.1 Java体系结构包括哪几部分?Java体系结构包括4个独立但相关的技术the Java programming language →程序设计语言the Java class file format →字节码文件格式the Java Application Programming Interface→应用编程接口the Java Virtual Machine →虚拟机1.2 什么是JVMjava虚拟机和java API组成了java运行时。

1.3 JVM的主要任务。

Java虚拟机的主要任务是装载class文件并执行其中的字节码。

Java虚拟机包含了一个类装载器。

类装载器的体系结构二种类装载器启动类装载器用户定义的类装载器启动类装载器是JVM实现的一部分当被装载的类引用另外一个类时,JVM就是使用装载第一个类的类装载器装载被引用的类。

1.4 为什么java容易被反编译?●因为java程序是动态连接的。

从一个类到另一个类的引用是符号化的。

在静态连接的可执行程序中。

类之间的引用只是直接的指针或者偏移量。

相反在java的class文件中,指向另一个类的引用通过字符串清楚的标明了所指向的这个类的名字。

●如果引用是指向一个字段的话。

这个字段的名字和描述符(字段的类型)会被详细说明。

●如果引用指向一个成员方法,那么这个成员方法的名字和描述符(方法的返回值类型,方法参数的数量和类型)会被详细说明。

●包含对自己字段和成员方法的符号引用。

●包含可选的调试信息。

(包括局部变量的名称和类型)1.5 垃圾回收器缺点:无法确认什么时候开始回收垃圾,无法确认是否已经开始收集,也无法确认要持续多长时间2平台无关3安全4网络移动性5Java虚拟机●每个JVM都有一个类装载子系统。

●运行时数据区:方法区,堆,java栈,pc寄存器,本地方法栈●每个JVM实例都有一个方法区和堆。

他们是由该虚拟机中所有线程共享的。

●每个线程都会得到自己的pc寄存器和java栈,⏹pc寄存器的值指示下一条将被执行的指令。

⏹java栈记录存储该线程中java方法调用的状态。

(包括局部变量,参数,返回值,运算的中间结果。

)⏹这些内存区域是私有的。

任何线程都不能访问另一个线程的pc寄存器和java栈●java栈由许多栈帧组成。

一个栈帧包含一个java方法的调用的状态。

⏹当线程调用一个方法的时候,虚拟机压入一个新的栈桢到该线程的java栈中。

⏹当方法返回时,这个栈桢被从java栈中弹出并抛弃。

●引用有3中,类类型,接口类型,数组类型。

●JVM中,最基本的数据单元是字。

至少选择32位作为字长。

●JVM有两种类装载器:⏹启动类装载器(JVM实现的一部分,每个JVM都必须有一个)⏹用户自定义的类装载器(JA V A程序的一部分,必须继承ng.CloassLoader)。

●由不同的类装载器装载的类被放在虚拟机内部的不同的命名空间中。

●方法区:⏹大小不固定,根据需要动态调整⏹方法区可以被垃圾回收⏹包含◆提取装载的类的信息,放到方法区●JVM总能通过存储于方法区的内存信息来确定一个对象需要多少内存◆类的静态变量也放到方法区。

⏹虚拟机为装载的每个类存储如下信息:◆这个类型的全限定名◆这个类型的直接超类的全限定名◆这个类型是类类型还是接口类型◆这个类的访问权限修饰符◆任何直接超接口的全限定名的有序列表◆该类型的常量池●该类型所用常量的一个有序集合,包括直接常量(String,Integer,floatingpoint),和对其他类型,字段,方法的符号引用◆字段信息●字段名●字段类型●字段的修饰符●声明的顺序◆方法信息●方法名●方法的返回值类型●方法的参数和类型,顺序●方法的修饰符●方法的操作码●操作数栈和该方法的栈帧中局部变量区的大小●异常表◆除了常量以外的所有类(静态)变量◆一个到类CloassLoader的引用◆一个到Class类的引用◆方法表●虚拟机为每一个装载的非抽象类都生成一个方法表⏹堆◆◆一个java程序独占一个JVM,一个JVM中只存在一个堆。

所以,每个java程序有它自己的堆,但同一个java程序的多个线程共享一个堆◆运行时创建的所有类实例◆数组对象⏹垃圾回收器◆回收内存◆移动对象以减少碎片◆不必是连续的内存,可以动态的扩展和收缩◆一个JVM的实现的方法区可以在堆顶实现⏹栈帧◆栈帧由3部分组成:局部变量区,操作数栈,帧数据区。

◆局部变量区,操作数栈的大小在编译的时候就确定了。

◆局部变量区●以字长为单位,从0开始计数的数组。

●int,float,reference,return address只占据一个字长●byte,short,char存入数组前转换成int,占据一个字长●long,double占据2个字长。

●包含对应方法的参数和局部变量,●方法的局部变量任意决定顺序,甚至一个索引指代两个变量,(当2个变量的作用域不重复时)◆操作数栈●以字长为单位的数组,但不是通过索引来访问,而是通过标准的栈操作●存贮数据的方式和局部变量区一样。

◆帧数据区●帧数据区保存常量池解析,正常方法返回,异常派发机制等信息◆执行引擎◆线程:●JVM只规定了最高级别的线程会得到大多数的CPU时间,●较低优先级别的线程,只有在所有比它优先级更高的线程全部阻塞的情况下才能保证得到CPU时间。

●级别低的线程在级别高的线程没有被阻塞的时候,也可能得到CPU时间,但是这没有任何保证。

●每个虚拟机都有一个主存,用于保存所有的程序变量(对象的实例变量,数组的元素,以及类变量)。

每一个线程都有一个工作内存,线程用它保存所使用和赋值的“工作拷贝”。

●局部变量和参数,因为他们是每个线程私有的,可以逻辑上看成是工作内存或者主存的一部分。

6字节码文件8位字节的二进制流常量池标志每一个标志都有一个相对应的表。

表名通过在标志后面加上"_info"后缀来产生7类型的声明周期●装载⏹通过该类型的完全限定名,产生一个该类型的二进制数据流⏹解析这个二进制数据流为方法区内的内部数据结构⏹(并在堆上)创建一个表示该类型的ng.Class类的实例●连接(已读入的二进制形式的类型数据合并到虚拟机的运行时状态中去)⏹验证(保证java类型数据格式正确并适合JVM使用)⏹准备(分配内存,默认初始化在此时发生)⏹解析(把常量池中的符号引用(类,接口,字段,方法)转换为直接引用,虚拟机的实现可以推迟解析这一步,它可以在当运行中的程序真正使用某个符号引用是再去解析它)●初始化(将类变量赋予适当的初始值(显式初始化),所有JVM的实现必须在每个类或接口首次主动使用是被初始化)对象的生命周期●类实例化有四种途径:⏹new⏹调用Class或者ng.reflect.Constructor的newInstance ( )⏹clone ( )⏹java.io.ObjectInputStream的getObject ( )8连接模型●动态连接和解析●常量池:⏹class文件把它所有的引用符号保存在一个地方,常量池⏹每个文件有一个常量池⏹每一个被JVM装载的类或者接口都有一份内部版本的常量池,被称作运行时常量池⏹运行时常量池映射到class文件的常量池⏹JVM为每一个装载的类和接口保存一份独立的常量池。

⏹来自相同方法或不同方法中的几条指令,可能指向同一个常量池入口。

⏹每个常量池入口只被解析一次。

●解析⏹在程序运行的某些时刻,如果某个特定的符号引用将要被使用,它首先要被解析。

⏹解析过程就是根据符号引用查找到实体,在把符号引用替换成直接引用的过程。

⏹所有的符号引用都保持在常量池,所以这个过程也被称作常量池解析。

⏹解析分为早解析和迟解析。

9垃圾收集10栈和局部变量操作Stack and Local Variable Operations10.1 常量入栈操作Pushing Constants Onto the Stack10.1.1将一个字长的常量压入栈10.1.2将一个字长的常量压入栈long and double values occupy 64 bits. Each time a long or double is pushed onto the stack, its value occupies two slots on the stack.long和double类型的值是64位长度的值,每当一个long或者double类型的值被压入栈,将占据2个位置10.1.3将空的对象引用(null)压入栈One other opcode pushes an implicit constant value onto the stack. The aconst_null opcode, pushes a null object reference onto the stack.Opcode Operand(s) Descriptionaconst_null (none) pushes a null object reference onto the stack10.1.4将byte和short类型常量压入栈10.1.5将常量池入口压入栈Pushing constant pool entries onto the stackOpcode Operand(s) Descriptionldc indexbyte1 pushes single-word value from constant pool entryspecified by indexbyte1 onto the stackldc_w indexbyte1,indexbyte2 pushes single-word value from constant pool entry specified by indexbyte1, indexbyte2 onto the stackldc2_w indexbyte1,indexbyte2 pushes dual-word value from constant pool entry specified by indexbyte1, indexbyte2 onto the stack10.2 通用栈操作Generic Stack Operations10.2.1栈操作Stack manipulationOpcode Operand(s) Descriptionnop (none) do nothingpop (none) pop the top word from the operand stackpop2 (none) pop the top two words from the operand stackswap (none) swap the top operand stack two wordsdup (none) duplicate top operand stack worddup2 (none) duplicate top two operand stack wordsdup_x1 (none) duplicate top operand stack word and put two downdup_x2 (none) duplicate top operand stack word and put three downdup2_x1 (none) duplicate top two operand stack words and put three down dup2_x2 (none) duplicate top two operand stack words and put four down10.3 把局部变量压入栈Pushing Local Variables Onto the Stack10.3.1将1个字长的局部变量压入栈Pushing single-word local variables onto the stackOpcode Operand(s) Descriptioniload vindex pushes int from local variable position vindexiload_0 (none) pushes int from local variable position zeroiload_1 (none) pushes int from local variable position oneiload_2 (none) pushes int from local variable position twoiload_3 (none) pushes int from local variable position threefload vindex pushes float from local variable position vindexfload_0 (none) pushes float from local variable position zerofload_1 (none) pushes float from local variable position onefload_2 (none) pushes float from local variable position twofload_3 (none) pushes float from local variable position three10.3.2将2个字长的局部变量压入栈Pushing dual-word local variables onto the stackOpcode Operand(s) Descriptionlload vindex pushes long from local variable positions vindex and (vindex+ 1)lload_0 (none) pushes long from local variable positions zero and onelload_1 (none) pushes long from local variable positions one and twolload_2 (none) pushes long from local variable positions two and threelload_3 (none) pushes long from local variable positions three and four dload vindex pushes double from local variable positions vindex and(vindex + 1)dload_0 (none) pushes double from local variable positions zero and one dload_1 (none) pushes double from local variable positions one and twodload_2 (none) pushes double from local variable positions two and three dload_3 (none) pushes double from local variable positions three and four10.3.3将对象引用局部变量压入栈Table 10-9. Pushing object reference local variables onto the stackOpcode Operand(s) Descriptionaload vindex pushes object reference from local variable position vindex aload_0 (none) pushes object reference from local variable position zero aload_1 (none) pushes object reference from local variable position one aload_2 (none) pushes object reference from local variable position two aload_3 (none) pushes object reference from local variable position three10.4 弹出栈顶部元素,将其赋给局部变量Popping to Local Variables10.4.1弹出一个字长的值,将其赋给局部变量Popping single-word values into local variablesOpcode Operand(s) Descriptionistore vindex pops int to local variable position vindexistore_0 (none) pops int to local variable position zeroistore_1 (none) pops int to local variable position oneistore_2 (none) pops int to local variable position twoistore_3 (none) pops int to local variable position threefstore vindex pops float to local variable position vindexfstore_0 (none) pops float to local variable position zerofstore_1 (none) pops float to local variable position onefstore_2 (none) pops float to local variable position twofstore_3 (none) pops float to local variable position three10.4.2弹出2个字长的值,将其赋给局部变量Popping dual-word values into local variablesOpcode Operand(s) Descriptionlstore vindex pops long to local variable positions vindex and (vindex + 1) lstore_0 (none) pops long to local variable positions zero and onelstore_1 (none) pops long to local variable positions one and twolstore_2 (none) pops long to local variable positions two and threelstore_3 (none) pops long to local variable positions three and fourdstore vindex pops double to local variable positions vindex and (vindex +1)dstore_0 (none) pops double to local variable positions zero and onedstore_1 (none) pops double to local variable positions one and twodstore_2 (none) pops double to local variable positions two and threedstore_3 (none) pops double to local variable positions three and four10.4.3弹出对象引用,将其赋给局部变量Popping object references into local variablesOpcode Operand(s) Descriptionastore vindex pops object reference to local variable position vindexastore_0 (none) pops object reference to local variable position zeroastore_1 (none) pops object reference to local variable position oneastore_2 (none) pops object reference to local variable position twoastore_3 (none) pops object reference to local variable position three10.5 wide指令The wide Instruction10.5.1弹出对象引用,将其赋给局部变量Popping object references into local variables无符号8位局部变量索引,把方法中的局部变量限制在256以下。

相关主题