抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

JVM整体介绍

JAVA技术体系结构

Java虚拟机(Java Virtual Machine 简称 JVM)是运行所有Java程序的抽象计算机,是Java语言的运行环境,它是Java 最具吸引力的特性之一。

Java虚拟机是整个Java技术体系最重要的基础。

为什么要了解虚拟机

  • 首先,Java 虚拟机提供了许多配置参数,用于满足不同应用场景下,对程序性能的需求。学习Java 虚拟机,你可以针对自己的应用,最优化匹配运行参数。

  • 其次,Java 虚拟机本身是一种工程产品,在实现过程中自然存在不少局限性。学习 Java 虚拟机,可以更好地规避它在使用中的 Bug,也可以更快地识别出 Java 虚拟机中的错误

  • 再次,Java 虚拟机拥有当前最前沿、最成熟的垃圾回收算法实现,以及即时编译器实现。学习Java 虚拟机,我们可以了解背后的设计决策,今后再遇到其他代码托管技术也能触类旁通。

  • 最后,Java 虚拟机发展到了今天,已经脱离 Java 语言,形成了一套相对独立的、高性能的执行方案。除了 Java 外,Scala、Clojure、Groovy,以及时下热门的 Kotlin,这些语言都可以运行在 Java 虚拟机之上。学习 Java 虚拟机,便可以了解这些语言的通用机制,甚至于让这些语言共享生态系统。

未来的Java技术

  • 模块化:OSGI(动态化、模块化),应用层面就是微服务,互联网的发展方向

  • 混合语言:多个语言都可以运行在JVM中,google的Kotlin 成为了 Android 的官方语言。Scala(Kafka)

  • 多核并行:CPU从高频次转变为多核心,多核时代。JDK1.7引入了Fork/Join,JDK1.8提出lambda表达式(函数式编程天生适合并行运行)

  • 丰富语法:JDK5提出自动装箱、泛型(并发编程讲到)、动态注解等语法。JDK7二进制原生支持。try-catch-finally 至try-with-resource

  • 64****位:虽然同样的程序64位内存消耗比32位要多一点,但是支持内存大,所以虚拟机都会完全过渡到64位,32位的JVM有4G的堆大小限制。

  • 更强的垃圾回收器(现在主流CMS、G1):JDK11 –ZGC(暂停时间不超过10毫秒,且不会随着堆的增加而增加,TB级别的堆回收)):有色指针、加载屏障。JDK12支持并发类卸载,进一步缩短暂停时间 JDK13(计划于2019年9月)将最大堆大小从4TB增加到16TB

JVM的整体介绍

JVM是如何工作的

JVM分成3个主要的子系统

  • 类加载器子系统

  • 运行时数据区

  • 执行引擎

类加载器子系统

Java的动态类加载功能是通过类加载子系统去处理的。

它并不是在编译时候,而是在首次运行时加载引用类时、连接并初始化类文件。

加载

类通过该组件加载。通过引导类加载器,扩展类加载器,应用类加载器这三个类加载器帮助完成加载。

  1. 引导类加载器

负责从引导类路径去加载类,除了rt.jar之外,没其他别的jar。给予该加载器最高的优先级。

  1. 扩展类加载器

负责加载ext目录(jre\lib)的类

  1. 应用加载器

负责加载类路径中应用级别的类,path提到的环境变量,等等。

以上的类加载器在加载类文件的时候遵循委托层次算法。

连接
  1. 验证-字节码验证器验证生成的字节码是否正确,如果验证失败,我们将收到验证的错误信息。
  2. 准备-为所有的静态变量分配内存和默认值
  3. 解析-用方法区的原始引用代替所有符号内存引用。
初始化

这是类加载的最后一个阶段,此时所有的静态变量都用原始值去赋值,并且将运行静态代码块。

运行时数据区

运行时数据区域分成5个主要的组件

方法区

所有类级的数据都存储在这里,包括静态变量。

每个JVM只有一个方法区,它是一个共享资源。

堆区

所有的对象和对应的实例变量以及数组都存储在这里。

每个JVM只有一个堆区,由于方法区和堆区为多个线程共享内存,所以存储的数据不是线程安全的。

栈区

为每个线程,创建一个单独的运行时栈。为每个方法调用,在栈内存创建一个条目,称之为栈帧。所有本地变量都会在栈内存中创建。由于它不是共享的资源,所有是线程安全的。

栈帧被分成3子实体

  1. 本地变量数组-涉及跟方法有关的本地变量和对应的值都存储在这里。
  2. 操作数栈-如果需要执行中间操作,操作数堆栈作为运行时工作区来执行操作。
  3. 帧数据-所有和对应方法的标记都存储在里面。在发生异常的情况下,捕捉块信息在这里维护。
程序计数器寄存器

每个线程都有自己的程序计数器寄存器,持有当前执行指令的地址,一旦当前指令执行被运行,下一个指令将会更新到程序计数器寄存器。

执行引擎

字节码被分配到执行引擎执行的运行时数据区。执行引擎一块一块的读取字节码并执行。

解释器

解释器解释字节码很快,但是执行的很慢。解释器的缺点是当一个方法被调用多次,每次都需要一个新的解释。

JIT编译器

JIT弥补了解释器的缺点。执行引擎将利用解释器转换字节码,但是当他找到重复的编码,它就使用编译器。编译器编译全部的字节码并变成本地代码

这些本地码将直接被方法调用重复地使用,这就改善了系统的性能。

  1. 中间代码生成器-生成中间代码。
  2. 代码优化器-负责优化上面生成的代码
  3. 目标代码生成器-负责生成机器码或者本地代码
  4. 分析器-一个特殊的组件,负责寻找hotspots,即是否方法被调用多次。
垃圾收集器

收集和清除未被引用的对象,可以通过System.gc()触发垃圾回收,但是不保证一定执行。创建收集对象的JVM垃圾收集。

Java Native Interface (JNI):JNI和本地方法库互动,特供本地库所需的执行引擎。

Native Method Libraries: 这是执行引擎所需的本地方法的一个集合

评论