前言:
在探索现代软件开发的丰富生态系统时,我们不可避免地会遇到一个强大而神秘的存在------Java虚拟机(JVM)。作为Java语言最核心的组成之一,JVM已经超越了其最初的设计目标,成为一个多语言的运行平台,支撑着企业级应用、大数据处理、移动应用等众多领域的技术栈。
JVM的独特之处在于它的架构设计,它不仅负责代码的执行,还包括了内存管理、垃圾回收、线程同步等高级功能,这些都是确保高效、稳定运行Java程序的关键因素。随着时间的推移,JVM经过不断的迭代和优化,集成了越来越多先进的性能改进技术,如即时编译(JIT)、热点代码检测、逃逸分析等。
而在本文中,我将为大家从基础层面介绍一下JVM,带领大家揭开JVM的神秘面纱。
目录
什么是JVM
Java虚拟机(JVM)是一个可以执行Java字节码的虚拟计算机。它是Java平台的核心部分,负责运行以Java编程语言编写并编译为Java字节码(.class文件)的程序 。JVM的存在使得Java语言能够实现其标志性的"一次编写,到处运行"(Write Once, Run Anywhere,WORA)的特性,因为JVM屏蔽了底层操作系统和硬件平台的差异。
我们可以通过以下流程图来了解JVM在JAVA程序中的作用
总结来讲:我们平时自己写的代码需要编译后转为字节码,而JVM再将字节码转为机器码,提交给电脑进行运行。而JVM的功能也不止这些。
1.JVM的功能:
-
跨平台性:Java语言使用"一次编写,到处运行"(Write Once, Run Anywhere,WORA)的理念,JVM是这一理念的实现基础。开发者只需编写一次Java代码,然后编译成与平台无关的字节码文件,这些字节码可以在任何安装了兼容JVM的设备上运行。
-
内存管理:JVM管理Java程序运行时所需的内存。它包括堆内存(Heap)用于存储对象实例,栈内存(Stack)用于存储局部变量和调用方法的上下文,方法区(Method Area)用于存储类信息,以及其他如程序计数器等结构。JVM还负责垃圾回收(Garbage Collection),自动管理对象的生命周期,回收不再使用的对象占用的内存空间。
-
执行引擎:JVM中的执行引擎负责解释字节码或通过即时编译器(Just-In-Time Compiler, JIT)将字节码转换为本地机器码执行,从而提高程序的性能。
-
安全性:JVM提供了一个相对封闭和安全的执行环境,可以对加载的字节码进行验证,确保其不会执行非法操作。JVM的安全管理器和类加载器也参与到安全检查中,防止恶意代码损害系统。
-
多语言支持:虽然JVM最初是为Java语言设计的,但现在它也支持其他语言,如Scala、Kotlin、Groovy等,甚至支持非JVM语言通过特定桥接技术运行在JVM上,如JRuby(Ruby语言的实现)和Jython(Python语言的实现)。
-
工具和生态系统:JVM提供了丰富的工具和API,如JConsole、VisualVM等,用于监控和调试运行在JVM上的程序。此外,围绕JVM形成了强大的生态系统,包括各种框架、库和工具,这些都大大增强了Java开发的便捷性和效率。
在这些功能中,即时编译是提升JAVA运行效率的最核心手段 ,因此我们这里来详细介绍一下即时编译:
即时编译:
在程序运行时将热点代码(经常执行的代码区域)编译成与本地平台相关的机器码,并且保存在本地。这样的话,当这些代码再次执行时就可以直接运行机器码,而不需要再次解释,从而大大提高了执行效率 。
即时编译的步骤:
-
热点探测:JIT编译器会监控哪些代码块(如方法或循环)被频繁执行,这些代码块被称为"热点代码"。
-
编译优化:当热点代码被识别后,JIT编译器会将这些代码编译成优化后的本地机器码。这个过程中,JIT编译器还会进行各种优化,比如内联展开、死码消除、循环优化等,以进一步提升性能。
-
代码替换:编译完成后,JVM会使用生成的机器码替换原先的字节码,之后的执行就不再需要解释器参与。
-
垃圾回收:即时编译生成的机器码也需要管理,当某部分代码不再是热点代码,或者JVM需要释放资源时,JIT编译器生成的机器码可能会被垃圾回收器清理掉。
2.常见的JVM:
-
Oracle HotSpot JVM:这是目前最流行的JVM实现,是Oracle公司的产品。HotSpot JVM具有良好的性能和可靠性,并且具有广泛的平台支持。
-
OpenJDK JVM:这是一个开源的JVM实现,是Oracle HotSpot JVM的基础。OpenJDK JVM由全球开发者社区维护和更新,提供了一种免费的Java运行环境。
-
IBM JVM:这是IBM(国际商业机器公司)开发的JVM实现,具有较高的性能和可靠性。IBM JVM主要用于IBM的服务器和企业级应用程序。
-
Azul Zing JVM:这是由Azul Systems开发的JVM实现,专注于提供卓越的性能和可伸缩性。Azul Zing JVM适用于高要求的应用程序,如金融交易系统和大规模数据处理。
-
GraalVM:这是一种新型的JVM实现,由Oracle开发。GraalVM是一款高性能的JVM,同时还支持其他编程语言,如JavaScript、Python和Ruby。
我们可以使用cmd快速查看自己的虚拟机:
这里标识我的虚拟机是 OpenJDK 11.0.16.1版本的Java虚拟机(JVM),并且它是64位的服务器版(Server VM)。这个特定的JVM构建是由Microsoft维护或构建的,支持混合模式执行(mixed mode),即能够在JIT编译模式和解释模式之间切换,以便在不同的场景下提供最佳性能。
3.JVM的组成部分:
-
类加载器子系统(Class Loader Subsystem):
- 负责从文件系统或网络等来源加载Class文件,Class文件在文件形式中是以二进制流的形式存在的,类加载器读取这些字节流,并将其转换成方法区的运行时数据结构。
- 在加载的过程中,类加载器还负责对字节码进行验证,确保其符合JVM规范,不会危害到JVM自身的安全。
- 类加载器通常分为启动(Bootstrap)类加载器、扩展(Extension)类加载器和应用程序(Application)类加载器等。
-
运行时数据区(Runtime Data Areas):
- 方法区(Method Area):存储每一个类的结构信息,如运行时常量池(Runtime Constant Pool)、字段和方法数据、构造函数和普通方法的字节码内容等。
- 堆(Heap):JVM管理的最大一块内存区域,用于存放对象实例和数组,是垃圾收集器管理的主要区域。
- 栈(Stacks**)**:每个线程包含一个栈,用于存储局部变量表、操作栈、动态链接、方法出口等信息。每个方法调用都会创建一个栈帧。
- 程序计数器(Program Counter Register):每个线程都有一个程序计数器,是一块较小的内存空间,它指示了线程当前正在执行的JVM指令地址。
- 本地方法栈(Native Method Stack):专门用于处理本地方法的调用。
-
执行引擎(Execution Engine):
- 负责执行类文件中的指令。当执行引擎接收到字节码时,它会进行解释或编译(通过即时编译器,JIT)成为本地机器指令执行。
- 包括解释器(Interpreter)和即时编译器(Just-In-Time Compiler, JIT)两部分。解释器快速解释执行字节码,而JIT编译器则可以提高性能,将热点代码(经常执行的代码)编译成与本地平台相关的机器码。
-
垃圾回收器(Garbage Collector):
- 用于自动管理JVM内存,特别是堆内存的分配与释放。当对象不再被引用时,垃圾回收器会回收这些对象占用的内存空间,释放资源。
-
本地方法接口(JNI)与本地方法库(Native Libraries):
- Java Native Interface(JNI)是一个框架,允许Java代码和其他语言写的代码互相调用,比如C/C++编写的应用程序或库。
- 本地方法库是一组特定于特定操作系统的库,由JNI调用,用于执行那些不能直接用Java实现的任务。
JVM的这些组成部分共同工作,提供了一个完整、高效且稳定的Java运行时环境。通过不断地优化和改进这些组件,JVM能够支持高性能的并发和垃圾回收策略,同时确保了跨平台的可移植性和安全性。
总结:
在本文中我们为大家介绍了JVM的基本组成和各个部分的功能,相信通过这一部分的讲解,大家已经能够理解JVM的作用。
如果我的内容对你有帮助,请点赞,评论,收藏。创作不易,大家的支持就是我坚持下去的动力!