推广 热搜: csgo  vue  angelababy  2023  gps  新车  htc  落地  app  p2p 

Java虚拟机架构详解

   2023-08-07 网络整理佚名2710
核心提示:但不是所有的代码都是解释执行的,JVM对此做了优化,比如,以虚拟机来说,它本身提供了JIT()典型的应用是x86的二进制指令集:比如传统的pc以及安卓的虚拟机不同平台CPU架构不同,所以不能设计为基于寄存器的。Java虚拟机的架构模型采用解释器与编译器并存的架构它负责加载环境变量或系统属性java.开发人员通过继承抽象类java.Java虚拟机整体架构

所谓虚拟机,就是虚拟的计算机。 它是一个用于执行一系列虚拟计算机指令的软件。

虚拟机概念

系统虚拟机

程序虚拟机

虚拟机的分类

Java虚拟机是二进制字节码的运行环境。

负责将字节码加载到其内部。

解释/编译成对应平台的机器指令并执行。

影响

编译一次即可运行

自动内存管理

自动垃圾收集

特征

地点

整体架构图

Java编译器在编译过程中,如果任意一个节点执行失败,则编译失败

虽然每个平台上的Java虚拟机的实现细节不同,但是它们一起执行的字节码内容是相同的。

JVM的主要任务是将字节码加载到其内部,解释/编译成相应平台(Linux...)上的机器指令(即:汇编语言)

java虚拟机使用类加载器()来加载类文件

类加载完成后,会进行字节码验证。 字节码验证通过后,JVM解释器会将字节码翻译成机器代码(即:汇编语言)供操作系统执行。

但并不是所有的代码都会被解释执行,JVM对此进行了优化。 比如就虚拟机而言,它本身就提供了JIT()

实施流程

Java字节码执行流程

更易于设计和实现,适合资源受限的系统

避免寄存器分配问题:使用零地址指令进行分配(不需要地址,只需push和pop操作)

大部分指令都是零地址指令,其执行依赖于操作栈。指令集较小,编译器易于实现

无需硬件支持,可移植性更好,跨平台实现更好。

基于堆栈的指令集架构

典型应用是x86二进制指令集:如传统pc和虚拟机

指令集架构完全依赖于硬件,可移植性差

更高效的性能和执行

完成操作所需的指令更少

大多数情况下,基于寄存器架构的指令集往往以一地址指令、二地址指令和三地址指令为主,而基于堆栈架构的指令集则以零地址指令为主

基于寄存器的指令集架构

总结:由于跨平台的设计,Java指令是基于栈来设计的。 不同平台的CPU架构不同,所以不能设计成基于寄存器的。优点是跨平台,指令集小,编译器容易实现。 缺点是性能下降,需要更多的指令才能实现同样的功能。

Java虚拟机架构模型

Java虚拟机的启动是通过引导类加载器()创建初始化类()来完成的,初始化类由虚拟机的具体实现指定。

启动

运行中的Java虚拟机有一个明确的使命:执行Java程序

当程序开始执行时运行,当程序结束时停止

当所谓的Java程序执行时,实际执行的是一个称为Java虚拟机的进程。

跑步

跨度样式=\

程序在执行过程中遇到异常或错误时异常终止

Java虚拟机进程因操作系统错误而终止

线程调用类或类的退出方法,或者类的halt方法,Java安全管理器允许这种退出或halt操作

另外,JNI()规范描述了Java虚拟机在用于加载或卸载Java虚拟机时的退出

辞职

Java虚拟机的生命周期

Java虚拟机简介

采用解释器和编译器共存的架构

类加载子系统负责从文件系统或网络加载类文件,类文件在文件开头有特定的文件标识符

它只负责加载class文件,至于能否运行则由(执行引擎)决定

加载的信息存储在称为方法区的内存空间中。 除了类信息之外,方法区还存储运行时常量池信息,其中还可能包括字符串文字和数值常量(这部分常量信息是类文件中常量池部分的内存映射)

获取通过其完全限定名称定义此类的二进制字节流

将这个字节流表示的静态存储结构转换为方法区font color=\"#\"face=\的运行时数据结构

在堆区生成一个代表该类的java.lang.Class对象,作为方法区该类的各种数据的访问入口

A。 Class对象封装了方法区中类的数据结构,为java程序员提供了访问方法区数据结构的接口

b. 类加载的最终产物是位于堆区的Class对象;

C。 这里你可能会混淆堆区和方法区。 类对象存储在堆区,而不是方法区。 元数据不是类的Class对象! ! ,类的元数据存在于方法区

d. Class对象是加载的最终产物。 类的方法代码、变量名、方法名、访问权限、返回值等都在方法区

e. 当JVM加载一个类时,它会创建(JVM中的数据结构)来表示它的元数据,包括常量池、字段、方法等,这些元数据都存储在方法区中

F。 当创建一个新对象时,JVM 创建它来表示该对象并将其存储在堆中

阐明:

直接从本地系统加载

通过网络获取,典型场景:

从zip包中获取,未来将成为jar、war格式的基础

运行时计算生成,用得最多的是:动态代理技术

由其他文件生成,典型场景:JSP应用

从专有数据库中提取.class文件,相对较少

从加密文件中获取,针对.class文件反编译的典型防护措施

补充:加载.class文件的方式

加载

目的是保证class文件字节流中包含的信息满足当前虚拟机的要求,保证加载的类的正确性,不危及虚拟机本身的安全

文件格式验证

元数据验证

字节码验证

符号引用验证

主要包括四类验证:

核实

为类变量分配内存并设置类变量的默认初始值

这里不包括final修饰,因为final会在编译时分配,准备阶段会显式初始化

这里不会初始化实例变量,类变量会分配在方法区,实例变量会和对象一起分配到Java堆中

准备

将常量池中的符号引用转换为直接引用的过程

事实上,解析操作往往伴随着初始化后的JVM执行

符号引用是描述被引用对象的一组符号。符号引用的字面形式在《Java虚拟机规范》的Class文件格式中有明确的定义。 直接引用是直接指向目标的指针、相对偏移量或间接定位目标的句柄。

解析动作主要是针对类或接口、字段、类方法、接口方法、方法类型等。对应常量池中的、fo、nfo等

直接引用:是直接指向目标的指针、相对偏移量或间接定位目标的句柄。

补充:

分析

关联

初始化阶段是执行类构造方法()的过程

该方法不需要定义,它是Javac编译器自动收集的类中所有类变量的赋值动作与静态代码块中语句的组合,如果不定义就没有()font color= \"#\"脸=\

构造方法中的指令按照语句在源文件中出现的顺序执行

() 与类构造函数不同。 (注:从虚拟机的角度来看构造函数是())

如果类有父类,JVM会确保父类的()在子类的()执行之前已经执行。

虚拟机在多线程下必须保证类的()方法被同步锁定

初始化

加载、验证、准备和初始化这四个阶段发生的顺序是确定的,但是解析阶段不是一定的,在某些情况下它可以在初始化阶段之后开始,这是为了支持Java语言的运行时绑定(也称为动态绑定或后期绑定)

另请注意,这里的几个阶段是按顺序启动的,而不是按顺序或完成的,因为这些阶段通常是相互混合的,通常在一个阶段的执行过程中调用或激活另一个阶段

注意:

类加载过程

存在于本地硬盘上,可以理解为设计者在纸上绘制的模板,最后执行时会加载到JVM中,根据这个文件实例化n个相同的实例

加载到JVM中的称为放置在方法区的DNA元素模板

在.class文件-->JVM-->最终成为元数据模板,这个过程需要一个运输工具(类加载器)来扮演快递员的角色

JVM支持两种类型的类加载器,即:引导类加载器( class )和自定义类加载器(User-)

从概念上来说,自定义类加载器一般是指开发者在程序中自定义的一类类加载器,但这在Java虚拟机规范中并没有定义,而是加载所有由抽象类派生的类。类加载器

这个类加载是用C/C++语言实现的,嵌套在JVM内部 font color=\"#\"face=\

用于加载Java的核心类库(/jre/lib/rt.jar、.jar或者sun.boot.class.path路径下的内容),用户提供jvm本身需要的类

不继承自java.lang.,没有父加载器

加载扩展类和应用程序类加载器,并将它们指定为其父类加载器

出于安全考虑,启动类加载器只加载以包名开头的类:java、javax、sun等。

启动类加载器(引导类加载器:)

用Java语言编写,由sun.misc.$实现。

派生自类

父类加载器是启动类加载器

从java.ext.dirs系统属性指定的目录加载类库,或者从JDK安装目录的jre/lib/ext子目录(扩展目录)加载类库,如果放置的是用户创建的JAR在此目录下,也由扩展类加载器自动加载

扩展类加载器()

用java语言编写,作者:sun.misc.$er

父类加载器是扩展类加载器

它负责加载环境变量或系统属性java.class.path指定的路径下的类库

该类加载器是程序中默认的类加载器。 一般来说,Java应用程序的类都是由它加载的。

类加载器可以通过#()方法获取。

应用程序类加载器(系统类加载器,呃)

不管类加载器怎么划分,程序中最常见的类加载器永远只有3个

在Java的日常应用开发中,类的加载几乎都是通过以上三类加载器的配合来完成的。 必要时我们还可以自定义类加载器来自定义类的加载方法

定义

隔离加载类

修改类加载方式 font color=\"#\"face=\

扩展负载源

防止源代码泄露

开发者通过继承抽象类java.lang来实现自己的类加载器。 以满足一些特殊需求

JDK1.2之前,自定义类加载器时,总是继承类并重写()方法来实现自定义类加载类,但是JDK1.2之后,不再建议用户重写()方法,而是建议在()方法中编写自定义类加载逻辑

在编写自定义类加载器时,如果没有太复杂的需求,可以直接接触类,这样就避免了自己去写()方法和获取字节码流的方式,使得自定义类加载器的编写更简洁

定义类加载器的实现步骤

自定义类加载器

分类

类加载器

类加载子系统

电脑寄存器

虚拟机栈

本地方法栈

Java虚拟机整体架构

JVM 架构笔记

 
反对 0举报 0 收藏 0 打赏 0评论 0
 
更多>同类资讯
推荐图文
推荐资讯
点击排行
网站首页  |  关于我们  |  联系方式  |  使用协议  |  版权隐私  |  网站地图  |  排名推广  |  广告服务  |  积分换礼  |  网站留言  |  RSS订阅  |  违规举报
Powered By DESTOON