热门标签 | HotTags
当前位置:  开发笔记 > 前端 > 正文

JVM类运行机制实现原理解析

这篇文章主要介绍了JVM类运行机制实现原理解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

1.一段java程序是如何运行起来的呢?

Java源文件,通过编译器,产生.Class字节码文件,字节码文件通过Java虚拟机中的解释器,编译成特定及其上的机器码,那Java虚拟机又是怎样加载java程序并执行起来的呢?

简单来说:通过类加载器加载字节码文件,被分配到JVM的运行时数据区的字节码会被执行引擎执行。

(1)类加载器,加载.class文件

(2)运行数据区:栈区、堆区、PC寄存器、本地方法栈、方法区

(3)执行引擎:执行包在装载类方法中的指令

2. 类加载器

类的加载是指将类的.class文件读入内存,将其放在方法区内,然后在堆区创建一个java.lang.Class对象,用来封装类在方法区内的数据结构,并向java程序员提供访问方法区内数据结构的接口。类加载器并不需要等到某个类被首次主动使用时再加载它,JVM允许类加载器在预料某个类将要被使用时就预先加载它。

类的生命周期

类加载过程包括:加载、验证、准备、解析、初始化

(1)加载:查找并加载类的二进制数据。

a. 通过一个类的全限定名来获取其定义的二进制字节流

b. 将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构

c. 在Java堆中生成一个代表这个类的java.lang.Class,作为对方法区中这些数据的访问入口

(2)连接:

a. 验证:确保被加载类的正确性

b. 准备:为类的静态变量分配内存,并将其初始化为默认值

c. 解析:把类中的符号引用转换为直接引用

(3)初始化:为类的静态变量赋予正确的初始值

类加载器

  

启动类加载器:BootstrapClassLoader,负责加载存放在JDK\jre\lib或被-Xbootclasspath参数指定的路径中的,并且能被虚拟机识别的类库。

扩展类加载器:ExtensionClassLoader,负责加载DK\jre\lib\ext目录中,或者由java.ext.dirs系统变量指定的路径中的所有类库。

引用程序类加载器:ApplicationClassLoader,负责加载用户路径ClassPath所指定的类

JVM类加载机制

全盘负责:当一个类加载器负责加载某个Class时,该Class所依赖的和引用的其他Class也将由该类加载器负责载入,除非显示使用另外一个类加载器来载入

父类委托:先让父类加载器驶入加载该类,只有在父类加载器无法加载该类时才尝试从自己的类路径中加载该类

缓存机制:保证所有加载过的类都会被缓存,当需要使用某个类时,先从缓存区寻找该Class,只有缓存区不存在该类时,才会去加载此类。

双亲委派机制

意义:系统类防止内存出出现多分同样的字节码;保证Java程序安全稳定运行

(1)当AppClassLoader去加载一个class时,它首先不会自己去加载这个类,而是把类加载请求委派给父类加载器ExtClassLoader去完成。

(2)当ExtClassLoader去加载一个class时,它首先也不会自己去加载这个类,而是把类加载请求委派给BootStrapClassLoader去完成。

(3)如果BootStrapClassLoader加载失败,会使用ExtClassLoader来尝试加载。

(4)如果ExtClassLoader加载失败,会使用AppClassLoader来加载

(5)如果AppClassLoader也加载失败,则会爆出异常ClassNotFoundException

3. 运行数据区

(1)虚拟机栈:每个线程有一个私有的栈,随着线程的创建而创建。栈里面存着一种叫“栈帧”的东东,每个方法会创建一个栈帧,栈帧中存放局部变量表(基本数据类型和对象饮用)、操作数栈、方法出口等信息,栈的大小可以固定也可以扩展,当栈调用深度大于JVM所允许的范围,会抛出StackOverFlowError。

(2)本地方法栈:主要与虚拟机用到的native方法相关,java程序员不太关心。

(3)PC寄存器:也叫程序计数器。JVM支持多线程运行,每个线程都有自己的程序计数器。若当前执行的是JVM的方法,则该寄存器中保存当前执行指令的地址,若执行native方法,则为空。

(4)堆:堆内存是JVM所有线程共享的部分,虚拟机启动时就已经创建。所有对象和数组都在堆上进行分配。这部分空间可通过GC进行回收,当申请不到空间时会抛出OutOfMemoryError。

(5)方法区:所有线程共享。主要用于存储类的信息,常量池,方法数据,方法代码等。

4. 执行引擎

方法调用会导致栈帧的入栈,会确定调用哪一个方法。

(1)栈帧。程序的执行对应着栈帧的入栈和出栈,栈帧主要包括:局部变量表、操作数栈、动态连接、方法返回地址等。

(2)方法调用。

解析调用:类加载的解析阶段,会将其中一部分符号引用转化为直接引用,这种解析的前提是方法在程序真正运行之前就有一个可确定的调用版本。编译期可确定调用方法的版本:静态方法、私有方法、实例构造器、父类方法。
分派调用:

a. 静态分派:发生在编译阶段。所有依赖于静态类型来定位方法执行版本的分派动作成为静态分派,典型方法是重载。javac编译器根据参数的静态类型决定使用哪个重载版本。

b. 动态分派:运行期根据实际类型确定方法执行版本。与方法重写有密切关系。

c. 单分派和多分派:单分派是根据一个宗量对目标方法进行选择,多分派是根据多于一个宗量对目标方法进行选择。

(3)执行引擎需将字节码转换成可以直接被JVM执行的语言,可通过以下两种方式转换:

a. 解释器:一条一条的读取,解释并且执行字节码指令

b. 即时编译器:执行引擎首先按照解释执行的方式来执行,在合适的时候,即时编译器把整段字节码编译成本地代码。内置了JIT编译器的JVM都会检查方法的执行频率,如果一个方法的执行频率超过一个特定的值的话,那么这个方法就会被编译成本地代码。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。


推荐阅读
  • 六个接私活的平台,技术在手,财富自由!值得推荐给每一位专业人士!
    本文将介绍六个适合专业人士接私活的平台,帮助技术人才实现财富自由。这些平台不仅提供了丰富的项目机会,还为用户搭建了高效的合作桥梁,是每位技术人士不容错过的资源。 ... [详细]
  • Python作为当今IT领域中最受欢迎且高效的语言之一,其框架能够显著加速Web应用程序的开发过程。本文推荐并对比了十大顶级Python Web开发框架,其中CubicWeb以其卓越的代码重用性和模块化设计脱颖而出,为开发者提供了强大的支持。 ... [详细]
  • 探索 PHP 8.0 的重大更新:轻松获取年度月份数据
    PHP 8.0 引入了多项重要更新,包括增强的类型系统、全新的 JIT 编译器以及联合类型等特性。这些改进不仅提升了性能,还简化了开发流程。本文将重点介绍如何利用 PHP 8.0 的新功能轻松获取年度和月份数据,为开发者提供更高效、更简洁的解决方案。 ... [详细]
  • 深入解析Wget CVE-2016-4971漏洞的利用方法与安全防范措施
    ### 摘要Wget 是一个广泛使用的命令行工具,用于从 Web 服务器下载文件。CVE-2016-4971 漏洞涉及 Wget 在处理特定 HTTP 响应头时的缺陷,可能导致远程代码执行。本文详细分析了该漏洞的成因、利用方法以及相应的安全防范措施,包括更新 Wget 版本、配置防火墙规则和使用安全的 HTTP 头。通过这些措施,可以有效防止潜在的安全威胁。 ... [详细]
  • Django新手指南:第三步——构建你的首个项目
    在本教程中,我们将引导你完成创建第一个Django应用的步骤。通过实际操作,你将逐步了解Django框架的核心概念和基本功能。从项目结构到视图和模板的实现,我们将详细介绍每个环节,帮助你快速上手并构建出一个功能完整的Web应用。 ... [详细]
  • Windows环境下详细教程:如何搭建Git服务
    Windows环境下详细教程:如何搭建Git服务 ... [详细]
  • 结语 | 《探索二进制世界:软件安全与逆向分析》读书笔记:深入理解二进制代码的逆向工程方法
    结语 | 《探索二进制世界:软件安全与逆向分析》读书笔记:深入理解二进制代码的逆向工程方法 ... [详细]
  • 如何在Windows 10中启用最后的正确配置以解决问题?
    在使用Windows 10操作系统时,如果因误操作导致系统出现问题,可以通过启用“最后一次正确配置”功能来恢复系统。该功能可帮助用户快速回滚至最近一次稳定状态,有效解决系统故障。具体操作步骤包括进入高级启动选项并选择“最后一次正确配置”项,从而实现系统的快速恢复。 ... [详细]
  • 作为140字符的开创者,Twitter看似简单却异常复杂。其简洁之处在于仅用140个字符就能实现信息的高效传播,甚至在多次全球性事件中超越传统媒体的速度。然而,为了支持2亿用户的高效使用,其背后的技术架构和系统设计则极为复杂,涉及高并发处理、数据存储和实时传输等多个技术挑战。 ... [详细]
  • 智能制造数据综合分析与应用解决方案
    在智能制造领域,生产数据通过先进的采集设备收集,并利用时序数据库或关系型数据库进行高效存储。这些数据经过处理后,通过可视化数据大屏呈现,为生产车间、生产控制中心以及管理层提供实时、精准的信息支持,助力不同应用场景下的决策优化和效率提升。 ... [详细]
  • openGauss安全管理体系结构与源代码解析综述
    本文综述了openGauss数据库的安全管理体系结构及其源代码解析。与数据库的其他功能模块不同,安全模块的功能并非集中实现,而是分散在数据库的各个业务逻辑环节中,为不同阶段提供相应的安全支持,从而形成多层次、全方位的安全防护体系。这不仅增强了系统的安全性,还提高了安全机制的灵活性和适应性。 ... [详细]
  • 本题库精选了Java核心知识点的练习题,旨在帮助学习者巩固和检验对Java理论基础的掌握。其中,选择题部分涵盖了访问控制权限等关键概念,例如,Java语言中仅允许子类或同一包内的类访问的访问权限为protected。此外,题库还包括其他重要知识点,如异常处理、多线程、集合框架等,全面覆盖Java编程的核心内容。 ... [详细]
  • 在Java中,匿名函数作为一种无名的函数结构,无法独立调用;而在JavaScript中,不仅有类似的匿名函数,还有立即执行函数(IIFE)和闭包等高级特性。立即执行函数同样基于匿名函数实现,但会在定义时立即执行,而闭包则通过嵌套函数来捕获外部变量,实现数据封装和持久化。这些不同的函数形式在实际开发中各有应用场景,理解其特点有助于更好地利用语言特性进行编程。 ... [详细]
  • 在Spring与Ibatis集成的环境中,通过Spring AOP配置事务管理至服务层。当在一个服务方法中引入自定义多线程时,发现事务管理功能失效。若不使用多线程,事务管理则能正常工作。本文深入分析了这一现象背后的潜在风险,并探讨了可能的解决方案,以确保事务一致性和线程安全。 ... [详细]
  • 深入解析Java虚拟机内存模型(JMM)及其核心机制
    为了深入理解Java内存模型(JMM),首先需要对计算机硬件体系有全面的认识,尤其是CPU与主存之间的多级缓存架构。这些硬件特性直接影响了JMM的设计和实现,确保在多线程环境下数据的一致性和可见性。 ... [详细]
author-avatar
乳酪杳杳
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有