前言 JVM是Java Virtual Machine(Java虚拟机)的缩写,JVM是一种用于计算设备的规范,它是一个虚构的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的。 ![]() JVM屏蔽了与具体操作系统平台相关的信息,使Java程序只需生成在Java虚拟机上一次编译,多次运行,具有跨平台性。JVM在执行字节码时,实际上最终还是把字节码解释成具体平台上的机器指令执行。 Java虚拟机包括一套字节码指令集、一组寄存器、一个栈、一个垃圾回收堆和一个存储方法区。 本文将简述以下内容:
正文 JVM是什么 JDK、JRE和JVM对比 ![]() JVM,JRE,JDK 都是 java 语言的支柱,他们分工协作。但不同的是 Jdk 和 JRE 是真实存在的,而 JVM 是一个抽象的概念,并不真实存在。 JDK JDK(Java Development Kit) 是 Java 语言的软件开发工具包(SDK)。JDK 物理存在,是 programming tools、JRE 和 JVM 的一个集合。 ![]() JRE JRE(Java Runtime Environment)Java 运行时环境,JRE 是物理存在的,主要由Java API 和 JVM 组成,提供了用于执行 java 应用程序最低要求的环境。 ![]() JVM JVM是一种用于计算设备的规范,它是一个虚构的计算机的软件实现,简单的说,JVM是运行byte code字节码程序的一个容器。 JVM的特点
JVM字节码 JVM使用Java字节码的方式,作为Java 用户语言 和 机器语言 之间的中间语言。实现一个通用的、 机器无关 的执行平台。 JVM能干什么 基于安全方面考虑,JVM 要求在 class 文件中使用强制性的语法和约束,但任意一门语言都可以转换为被 JVM 接受的有效的 class 文件。作为一个通用的、机器无关的执行平台,任何其他语言的实现者都可将 JVM 当作他的语言产品交付媒介。 JVM 中执行过程如下:
JVM生命周期
JVM组成架构 JAVA 代码执行过程如下: ![]() 1. 类加载器(Class Loader) 类加载器 负责加载程序中的类型(类和接口),并赋予唯一的名字予以标识。 JDK 默认提供的三种 ClassLoader如下: ![]() 类加载器的关系
类加载器的作用 Class Loader 实现 负责加载 Bootstrap Loader C++ %JAVA_HOME%/jre/lib, %JAVA_HOME%/jre/classes以及-Xbootclasspath参数指定的路径以及中的类 Extension ClassLoader Java %JAVA_HOME%/jre/lib/ext,路径下的所有classes目录以及java.ext.dirs系统变量指定的路径中类库 Application ClassLoader Java Classpath所指定的位置的类或者是jar文档,它也是Java程序默认的类加载器 双亲委托机制 Java中ClassLoader的加载采用了双亲委托机制,采用双亲委托机制加载类的时候采用如下的几个步骤:
ClassLoader隔离问题 每个类装载器都有一个自己的命名空间用来保存已装载的类。当一个类装载器装载一个类时,它会通过保存在命名空间里的类全局限定名(Fully Qualified Class Name)进行搜索来检测这个类是否已经被加载了。 JVM 及 Dalvik 对类唯一的识别是 ClassLoader id + PackageName + ClassName,所以一个运行程序中是有可能存在两个包名和类名完全一致的类的。并且如果这两个”类”不是由一个 ClassLoader 加载,是无法将一个类的示例强转为另外一个类的,这就是 ClassLoader 隔离。 双亲委托 是 ClassLoader类一致问题的一种解决方案,也是 Android 差价化开发和热修复的基础。 类装载器特点 Java提供了动态加载特性。在运行时的第一次引用到一个class的时候会对它进行装载(Loading) 、** 链接(Linking)** 和 ** 初始化(Initialization) ** ,而不是在编译时进行。不同的JVM的实现不同,本文所描述的内容均只限于Hotspot JVM。 JVM的类装载器负责动态装载,Java的类装载器有如下几个特点:
类装载器过程
![]()
把类中的变量初始化成合适的值。执行静态初始化程序,把静态变量初始化成指定的值。
2. 执行引擎(Execution Engine) 通过类装载器装载的,被分配到JVM的运行时数据区的字节码会被执行引擎执行。 执行引擎 以指令为单位读取 Java 字节码。它就像一个 CPU 一样,一条一条地执行机器指令。每个字节码指令都由一个1字节的操作码和附加的操作数组成。执行引擎 取得一个操作码,然后根据操作数来执行任务,完成后就继续执行下一条操作码。 不过 Java 字节码是用一种人类可以读懂的语言编写的,而不是用机器可以直接执行的语言。因此,执行引擎 必须把字节码转换成可以直接被 JVM 执行的语言。 字节码 可以通过以下两种方式转换成机器语言:
Java 字节码是解释执行的,但是没有直接在 JVM 宿主执行原生代码快。为了提高性能,Oracle Hotspot 虚拟机会找到执行最频繁的字节码片段并把它们编译成原生机器码。编译出的原生机器码被存储在非堆内存的代码缓存中。 通过这种方法(JIT),Hotspot 虚拟机将权衡下面两种时间消耗:将字节码编译成本地代码需要的额外时间和解释执行字节码消耗更多的时间。 ![]() 这里插入一下 Android 5.0 以后用的 ART 虚拟机使用的是 AOT 机制。
如果对java微服务、分布式、高并发、高可用、大型互联网架构技术、面试经验交流。感兴趣可以关注我的头条号,我会在微头条不定期的发放免费的资料链接,这些资料都是从各个技术网站搜集、整理出来的,如果你有好的学习资料可以私聊发我,我会注明出处之后分享给大家。欢迎分享,欢迎评论,欢迎转发 |
最全JVM总体概述
阅读(705) 评论(0)