栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 系统运维 > 运维 > Linux

虚拟机类加载

Linux 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

虚拟机类加载

JAVA虚拟机是什么
 

一般理解为以下三种:

  •    抽象规范。
  •    一个具体的实现。
  •    一个运行中的虚拟机实例

      Java虚拟机抽象规范仅仅是个概念,《The Java Virtual Machine Specificaiion》一书中详细地描述了规范内容。
       规范的具体实现,可能来自多个提供商,并存在于多个平台M它或者完全用软件实现。或者以硬件和软件相结合的方式来实现,下面是目前几个主流的Java虚拟机实现。

  • Java SE / Java EE:Hotspot,JRockit(Oracle);J9, JikesRVM(IBM);Zulu,Zing (Azul)
  • Android / Android兼容系统:Dalvik / ART
  • 研究性质的JVM::Jikes RVM,Maxine VM,Graal VM

       当运行一个Java程序的同时,也就在运行了一个Java虚拟机实例。 每个Java程序都运行于某个具体的Java虚拟机实现的实例上。


组成部分:

       在Java虚拟机(规范)中,一个虚拟机实例的行为是分别按照子系统、内存区、数据类型以及指令这几个术语来描述的。这些组成部分一起展示抽象的虚拟机的内部抽象体系结构。但是规范中对它们的定义并不是要强制规定Java虚拟机实现内部的体系结构,更多的是为了产格地定义这些实现的外部格征。来定义任何Java虚拟机实现都必须遵守的行为。

       下图中Java虚拟机(实现)的结构框图,包括在规范中描述的主要子系统和内存区。每个Java虚拟机都有一个类装载器子系统,它根据给定的全限定名来装类型(类或接口 )。 同样每个Java虚拟机都有一个执行引擎,它负责执行那当包含在被装载类的方法中的指令。

     Java虚拟机的主要任务是装载class文件并且执行其中的字码。Java 虚拟机包含一个类装载器(class loader),它可以从程序和API中装载class文件。Java API中只有程序执行时需要的那些类才会被装载。字节码由执行引擎来执行。

执行引擎:

      执行引擎是Java虚拟机的核心。在Java虚拟机规范中,执行引擎的行为使用指令集来定义。对于每条指令,规范都详细规定了当实现执行到该指令时应该处理什么。但是却对如何处理言之甚少。实现的设计者行权决定如何执行字节码,实现可以采取解释,即时编译或直接用芯片上的指令执行。

    操作字节码一般分为以下四种实现:

  • 最简单的执行引擎就是一次性解释字节码。
  • 另一种执行引擎更快,但是也更消耗内存,叫做“即时编译器:(just-in-time compiler)。在这种情况下,第一次被执行的字节码会被编译成本地机器代码。编译出的本地机器代码会被缓存(CodeCache),当方法以后被调用的时候可以重用。
  • 第三种执行引擎是自适应优化器。虚拟机(运行的实例)开始的时候解释字节码,会监视运行中程序的活动。记录下使用最频繁的代码段。程序运行的时候,虚拟机只把那些活动最频繁的代码(热点代码)编译成本地代码,其他的代码继续保留为字节码,一个自适应的优化器可以使得Java虚拟机在80%-90%的时间里执行被优化过的本地代出,而只需要编译10%-20%对性有影响的代码。
  • 最后一种虚拟机由硬件芯片构成。它用本地方法执行 Java字节码,这种执行引擎实际上是内嵌在芯片里的。

       前三种处理方式,都是在此前实现方式下进行的优化。在虚拟机中是相辅相成的。

 何为热点代码:1:被多次调用的方法  2:被多次执行的循环体

 阈值如何判断:

         方法计数器,统计被多次调用的方法次数,该计数器统计的并不是方法被调用的绝对次数,而是在一段时间内方法被调用的次数。server模式下默认是10000次,可以通过-XX:CompileThreshold来设置
       回边计数器,统计一个方法中循环体代码执行的绝对次数,在字节码中遇到控制流向后跳转的指令称为回边,主要通过OnStackReplacePercentage设置。

   

        指令集:方法的字节码流是由Java虚拟机的指令序列构成的,每一条指令包含一个单字节的操作码。后倒跟随0个或多个操作数。操作码表明需要执行的择作;操作数向Java虚拟机提供执行操作码需要的额外信息,操作码本身就已是规定了它是否需要跟随操作数,以及如果操作数的话,它是什么形式的。很多Java虚拟机的指令不包含操作数,仅仅是由一个操作码字节构成的,根据操作码的需要。虚拟机可能除了跟随操作码的操作数之外。还需要从另外一些存储区域得到操作数:当虚拟机执行一条指令的时候,可能使用当前常址池中的项、当前帧的局部变量中的值、或者位于当前帧操作数栈顶端的值。

运行时数据区:

        Java虚拟机运行一个程序时,它需要内存来存储许多东西。例如字节码,从已装载的class文件中得到的其他信息,程序创建的对象,传递给方法的参数,返回值,局部变量,以及运算的中间结果等。Java虚拟机把这些东西都组织到几个“运行时数据区”中,以使于管理。“运行时数据区”都会以某种形式存在每一个Java虚拟机实现中。但是规范对它们的描述却是相当抽象的,这些运行时数据区结构上的细节大多数都由具体实现的设计决定。

数据类型:

      Java虚拟机是通过某些数据类型来执行计算的,数据类型及其运算都是由Java虚拟机规范严格定义的。数据类型可以分为两种:基本类型和引用类型。基本类型的变量持有原始值。而引用类型的持有引用值。下图是具体的定义图:

字长的考量:

       Java虚拉机中最基本的数据单元就是字(word),它的大小是由每个虚拟机实现的设计者 来决定的。字长必须足够大,至少是一个字单元就足以持有byte、short、int、char、float、 return Address或者refercncc类型的值。而两个字单元就足以持有long(64bit)或者double(64bit)类型的值,因此, 虚拟机实现的设计者至少得选择32位作为字长,或者选择更为高效的字长大小。通常根据底层主机平台的指针长度来选择字长。

类装载器子系统:

       Java虚拟机有两种类装载器:启动类装载器和用户自定义类装载器。前者是Java虚拟机实现 的一部分,后者则是Java程序的一部分。由不同的类装载器装载的类将被放在虚拟机内部的不同命名空间中。

类加载的流程         

         一个类型从被加载到虚拟机内存中开始,到卸载出内存为止,它的整个生命周期将会经历加载、验证、准备、解析、初始化、使用和卸载七个阶段,其中验证、准备、解析三个部分统称为连接。这七个阶段的发生顺序如下图所示。

                               

        加载、验证、准备、初始化和卸载这五个阶段的顺序是确定的,类型的加载过程必须按照这种顺序按部就班地开始,而解析阶段则不一定:它在某些情况下可以在初始化阶段之后再开始,这是为了支持Java语言的运行时绑定特性(也称为动态绑定或晚期绑定)。请注意,这里笔者写的是按部就班地“开始”,而不是按部就班地“进行”或按部就班地“完成”,强调这点是因为这些阶段通常都是互相交叉地混合进行的,会在一个阶段执行的过程中调用、激活另一个阶段。

每一个步骤的开始时机:

      加载:《Java虚拟机规范》中并没有进行强制约束,这点可以交给虚拟机的具体实现来自由把握。但是对于初始化阶段,《Java虚拟机规范》则是严格规定了有且只有六种情况必须立即对类进行“初始化”(而加载、验证、准备自然需要在此之前开始):

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/613600.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号