Java虚拟机工作原理.docx

上传人:b****4 文档编号:4993279 上传时间:2022-12-12 格式:DOCX 页数:37 大小:175.54KB
下载 相关 举报
Java虚拟机工作原理.docx_第1页
第1页 / 共37页
Java虚拟机工作原理.docx_第2页
第2页 / 共37页
Java虚拟机工作原理.docx_第3页
第3页 / 共37页
Java虚拟机工作原理.docx_第4页
第4页 / 共37页
Java虚拟机工作原理.docx_第5页
第5页 / 共37页
点击查看更多>>
下载资源
资源描述

Java虚拟机工作原理.docx

《Java虚拟机工作原理.docx》由会员分享,可在线阅读,更多相关《Java虚拟机工作原理.docx(37页珍藏版)》请在冰豆网上搜索。

Java虚拟机工作原理.docx

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

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 求职职场 > 简历

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1