Java虚拟机工作原理.docx
- 文档编号:4993279
- 上传时间:2022-12-12
- 格式:DOCX
- 页数:37
- 大小:175.54KB
Java虚拟机工作原理.docx
《Java虚拟机工作原理.docx》由会员分享,可在线阅读,更多相关《Java虚拟机工作原理.docx(37页珍藏版)》请在冰豆网上搜索。
Java虚拟机工作原理
AstheJavaVirtualMachineisastack-basedmachine,almostallofitsinstructionsinvolvetheoperandstackinsomeway.Mostinstructionspushvalues,popvalues,orbothastheyperformtheirfunctions.
Java虚拟机是基于栈的(stack-basedmachine)。
几乎所有的java虚拟机的指令,都与操作数栈(operandstack)有关.绝大多数指令都会在执行自己功能的时候进行入栈、出栈操作。
1Java体系结构介绍
Javaísarchitecturearisesoutoffourdistinctbutinterrelatedtechnologies,eachofwhichisdefinedbyaseparatespecificationfromSunMicrosystems:
1.1Java体系结构包括哪几部分?
Java体系结构包括4个独立但相关的技术
theJavaprogramminglanguage程序设计语言
theJavaclassfileformat字节码文件格式
theJavaApplicationProgrammingInterface应用编程接口
theJavaVirtualMachine虚拟机
1.2什么是JVM
java虚拟机和javaAPI组成了java运行时。
1.3JVM的主要任务。
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都必须有一个)
⏹用户自定义的类装载器(JAVA程序的一部分,必须继承java.lang.CloassLoader)。
●由不同的类装载器装载的类被放在虚拟机内部的不同的命名空间中。
●方法区:
⏹大小不固定,根据需要动态调整
⏹方法区可以被垃圾回收
⏹包含
◆提取装载的类的信息,放到方法区
●JVM总能通过存储于方法区的内存信息来确定一个对象需要多少内存
◆类的静态变量也放到方法区。
⏹虚拟机为装载的每个类存储如下信息:
◆这个类型的全限定名
◆这个类型的直接超类的全限定名
◆这个类型是类类型还是接口类型
◆这个类的访问权限修饰符
◆任何直接超接口的全限定名的有序列表
◆该类型的常量池
●该类型所用常量的一个有序集合,包括直接常量(String,Integer,floatingpoint),和对其他类型,字段,方法的符号引用
◆字段信息
●字段名
●字段类型
●字段的修饰符
●声明的顺序
◆方法信息
●方法名
●方法的返回值类型
●方法的参数和类型,顺序
●方法的修饰符
●方法的操作码
●操作数栈和该方法的栈帧中局部变量区的大小
●异常表
◆除了常量以外的所有类(静态)变量
◆一个到类CloassLoader的引用
◆一个到Class类的引用
◆方法表
●虚拟机为每一个装载的非抽象类都生成一个方法表
●堆
◆
◆一个java程序独占一个JVM,一个JVM中只存在一个堆。
所以,每个java程序有它自己的堆,但同一个java程序的多个线程共享一个堆
◆运行时创建的所有类实例
◆数组对象
●垃圾回收器
◆回收内存
◆移动对象以减少碎片
◆不必是连续的内存,可以动态的扩展和收缩
◆一个JVM的实现的方法区可以在堆顶实现
●栈帧frame
◆栈帧由3部分组成:
局部变量区,操作数栈,帧数据区。
◆局部变量区,操作数栈的大小在编译的时候就确定了。
◆局部变量区(variableTable)
●以字长为单位,从0开始计数的数组。
●int,float,reference,returnaddress只占据一个字长
●byte,short,char存入数组前转换成int,占据一个字长
●long,double占据2个字长。
●包含对应方法的参数和局部变量,
●方法的局部变量任意决定顺序,甚至一个索引指代两个变量,(当2个变量的作用域不重复时)
◆操作数栈
●以字长为单位的数组,但不是通过索引来访问,而是通过标准的栈操作
●存贮数据的方式和局部变量区一样(就数据长度而言)。
●帧数据区
●帧数据区保存常量池解析,正常方法返回,异常派发机制等信息
●执行引擎
●线程:
●JVM只规定了最高级别的线程会得到大多数的CPU时间,
●较低优先级别的线程,只有在所有比它优先级更高的线程全部阻塞的情况下才能保证得到CPU时间。
●级别低的线程在级别高的线程没有被阻塞的时候,也可能得到CPU时间,但是这没有任何保证。
●每个虚拟机都有一个主存,用于保存所有的程序变量(对象的实例变量,数组的元素,以及类变量)。
每一个线程都有一个工作内存,线程用它保存所使用和赋值的“工作拷贝”。
●局部变量和参数,因为他们是每个线程私有的,可以逻辑上看成是工作内存或者主存的一部分。
6字节码文件
8位字节的二进制流
classFile表的格式
Type&
#9;Name
Count
u4
magic
1
u2
minor_version
1
u2
major_version
1
u2
constant_pool_count
1
cp_info
constant_pool
constant_pool_count-1
u2
access_flags
1
u2
this_class
1
u2
super_class
1
u2
interfaces_count
1
u2
interfaces
interfaces_count
u2
fields_count
1
field_info
fields
fields_count
u2
methods_count
1
method_info
methods
methods_count
u2
attributes_count
1
attribute_info
attributes
attributes_count
Constantpooltags常量池标志
每一个标志都有一个相对应的表。
表名通过在标志后面加上"_info"后缀来产生
EntryType
TagValue
Description
CONSTANT_Utf8
1
AUTF-8encodedUnicodestring
CONSTANT_Integer
3
Anintliteralvalue
CONSTANT_Float
4
Afloatliteralvalue
CONSTANT_Long
5
Alongliteralvalue
CONSTANT_Double
6
Adoubleliteralvalue
CONSTANT_Class
7
Asymbolicreferencetoaclassorinterface
CONSTANT_String
8
AStringliteralvalue
CONSTANT_Fieldref
9
Asymbolicreferencetoafield
CONSTANT_Methodref
10
Asymbolicreferencetoamethoddeclaredinaclass
CONSTANT_InterfaceMethodref
11
Asymbolicreferencetoamethoddeclaredinaninterface
CONSTANT_NameAndType
12
Partofasymbolicreferencetoafieldormethod
7类型的声明周期
●装载
⏹通过该类型的完全限定名,产生一个该类型的二进制数据流
⏹解析这个二进制数据流为方法区内的内部数据结构
⏹(并在堆上)创建一个表示该类型的java.lang.Class类的实例
●连接(已读入的二进制形式的类型数据合并到虚拟机的运行时状态中去)
⏹验证(保证java类型数据格式正确并适合JVM使用)
⏹准备(分配内存,默认初始化在此时发生)
⏹解析(把常量池中的符号引用(类,接口,字段,方法)转换为直接引用,虚拟机的实现可以推迟解析这一步,它可以在当运行中的程序真正使用某个符号引用是再去解析它)
●初始化(将类变量赋予适当的初始值(显式初始化),所有JVM的实现必须在每个类或接口首次主动使用是被初始化)
对象的生命周期
●类实例化有四种途径:
⏹new
⏹调用Class或者java.lang.reflect.Constructor的newInstance()
⏹clone()
⏹java.io.ObjectInputStream的getObject()
8连接模型
●动态连接和解析
●常量池:
⏹class文件把它所有的引用符号保存在一个地方,常量池
⏹每个文件有一个常量池
⏹每一个被JVM装载的类或者接口都有一份内部版本的常量池,被称作运行时常量池
⏹运行时常量池映射到class文件的常量池
⏹JVM为每一个装载的类和接口保存一份独立的常量池。
⏹来自相同方法或不同方法中的几条指令,可能指向同一个常量池入口。
⏹每个常量池入口只被解析一次。
●解析
⏹在程序运行的某些时刻,如果某个特定的符号引用将要被使用,它首先要被解析。
⏹解析过程就是根据符号引用查找到实体,在把符号引用替换成直接引用的过程。
⏹所有的符号引用都保持在常量池,所以这个过程也被称作常量池解析。
⏹解析分为早解析和迟解析。
9垃圾收集
10栈和局部变量操作StackandLocalVariableOperations
10.1常量入栈操作
PushingConstantsOntotheStack
10.1.1将一个字长的常量压入栈
Opcode
Operand(s)
Description
iconst_m1
(none)
pushesint-1ontothestack
iconst_0
(none)
pushesint0ontothestack
iconst_1
(none)
pushesint1ontothestack
iconst_2
(none)
pushesint2ontothestack
iconst_3
(none)
pushesint3ontothestack
iconst_4
(none)
pushesint4ontothestack
iconst_5
(none)
pushesint5ontothestack
fconst_0
(none)
pushesfloat0ontothestack
fconst_1
(none)
pushesfloat1ontothestack
fconst_2
(none)
pushesfloat2ontothestack
10.1.2将两个字长的常量压入栈
longanddoublevaluesoccupy64bits.Eachtimealongordoubleispushedontothestack,itsvalueoccupiestwoslotsonthestack.
long和double类型的值是64位长度的值,每当一个long或者double类型的值被压入栈,将占据2个位置
Opcode
Operand(s)
Description
lconst_0
(none)
pusheslong0ontothestack
lconst_1
(none)
pusheslong1ontothestack
dconst_0
(none)
pushesdouble0ontothestack
dconst_1
(none)
pushesdouble1ontothestack
10.1.3将空的对象引用(null)压入栈
Oneotheropcodepushesanimplicitconstantvalueontothestack.Theaconst_nullopcode,pushesanullobjectreferenceontothestack.
Opcode
Operand(s)
Description
aconst_null
(none)
pushesanullobjectreferenceontothestack
10.1.4将byte和short类型常量压入栈
Pushingbyteandshortconstantsontothestack
Opcode
Operand(s)
Description
bipush
byte1
expandsbyte1(abytetype)toanintandpushesitontothestack
将byte1(数据类型为byte)转换为int然后将其压入栈
sipush
byte1,byte2
expandsbyte1,byte2(ashorttype)toanintandpushesitontothestack
将byte1和byte2(数据类型为short)转换为int然后将其压入栈
10.1.5将常量池入口压入栈
Pushingconstantpoolentriesontothestack
Opcode
Operand(s)
Description
ldc
indexbyte1
pushessingle-wordvaluefromconstantpoolentryspecifiedbyindexbyte1ontothestack
ldc_w
indexbyte1,indexbyte2
pushessingle-wordvaluefromconstantpoolentryspecifiedbyindexbyte1,indexbyte2ontothestack
ldc2_w
indexbyte1,indexbyte2
pushesdual-wordvaluefromconstantpoolentryspecifiedbyindexbyte1,indexbyte2ontothestack
10.2通用栈操作
GenericStackOperations
10.2.1栈操作
Stackmanipulation
Opcode
Operand(s)
Description
nop
(none)
donothing
pop
(none)
popthetopwordfromtheoperandstack
pop2
(none)
popthetoptwowordsfromtheoperandstack
swap
(none)
swapthetopoperandstacktwowords
dup
(none)
duplicatetopoperandstackword
dup2
(none)
duplicatetoptwooperandstackwords
dup_x1
(none)
duplicatetopoperandstackwordandputtwodown
dup_x2
(none)
duplicatetopoperandstackwordandputthreedown
dup2_x1
(none)
duplicatetoptwooperandstackwordsandputthreedown
dup2_x2
(none)
duplicatetoptwooperandstackwordsandputfourdown
10.3把局部变量压入栈
PushingLocalVariablesOntotheStack
10.3.1将1个字长的局部变量压入栈
Pushingsingle-wordlocalvariablesontothestack
Opcode
Operand(s)
Description
iload
vindex
pushesintfromlocalvariablepositionvindex
iload_0
(none)
pushesintfromlocalvariablepositionzero
iload_1
(none)
pushesintfromlocalvariablepositionone
iload_2
(none)
pushesintfromlocalvariablepositiontwo
iload_3
(none)
pushesintfromlocalvariablepositionthree
fload
vindex
pushesfloatfromlocalvariablepositionvindex
fload_0
(none)
pushesfloatfromlocalvariablepositionzero
fload_1
(none)
pushesfloatfromlocalvariablepositionone
fload_2
(none)
pushesfloatfromlocalvariablepositiontwo
fload_3
(none)
pushesfloatfromlocalvariablepositionthree
10.3.2将2个字长的局部变量压入栈
Pushingdual-wordlocalvariablesontothestack
Opcode
Operand(s)
Description
lload
vindex
pusheslongfromlocalvariablepositionsvindexand(vindex+1)
lload_0
(none)
pusheslongfromlocalvariablepositionszeroandone
lload_1
(none)
pusheslongfromlocalvariablepositionsoneandtwo
lload_2
(none)
pusheslongfromlocalvariablepositionstwoandthree
lload_3
(none)
pusheslongfromlocalvariablepositionsthreeandfour
dload
vindex
pushesdoublefromlocalvariablepositionsvindexand(vindex+1)
dload_0
(none)
pushesdoublefromlocalvariablepositionszeroandone
dload_1
(none)
pushesdoublefromlocalvariablepositionsoneandtwo
dload_2
(none)
pushesdoublefromlocalvariablepositionstwoandthree
dload_3
(none)
pushesdoublefromlocalvariablepositionsthreeandfour
10.3.3将对象引用局部变量压入栈
Table10-9.Pushingobjectreferencelocalvariablesontothestack
Opcode
Operand(s)
Description
aload
vindex
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Java 虚拟机 工作 原理