一、组成及作用
JVM(Java Virtual Machine,Java虚拟机)是Java平台的核心组成部分,它负责执行Java字节码,为Java程序提供了一个跨平台运行的环境。
JVM主要由以下几个关键组成部分构成,每个部分都有其特定的作用:
1. 类加载器(Class Loader)
作用:负责查找并加载类的字节码文件(.class文件),然后构造出对应的java.lang.Class对象,并将这些类的元数据放入方法区。类加载器分为启动类加载器(Bootstrap ClassLoader)、扩展类加载器(Extension ClassLoader)、系统类加载器(Application ClassLoader)以及用户自定义类加载器。它们遵循双亲委派模型来确保类的安全加载。
2. 执行引擎(Execution Engine)
作用:负责解释或编译字节码成为机器码并执行。执行引擎包括即时编译器(JIT Compiler),能够将热点代码编译成本地机器码以提高执行效率。此外,还包括解释器(Interpreter)等组件,解释器直接解释执行字节码,而即时编译器则在运行时动态地将字节码转换为更高效的本地代码。
3. 运行时数据区(Runtime Data Area)
主要包括以下部分:
a.方法区(Method Area):存储类的结构信息,如常量池、字段、方法数据、构造函数、静态变量等。从Java 8开始,永久代被元空间(Metaspace)取代,元空间不在JVM堆内,而是使用本地内存。
b.堆(Heap):存放几乎所有的Java对象实例以及数组。堆是线程共享的,是垃圾回收的主要区域。
c.栈(Java Stack/Stack Memory):每个线程私有,存储方法调用时的局部变量表、操作数栈、动态链接、方法出口等信息。栈帧随着方法调用和返回而创建和销毁。
d.本地方法栈(Native Method Stack):与Java栈类似,但服务于Native方法,同样用于存储方法调用的状态。
e.程序计数器(Program Counter Register):当前线程所执行的字节码的行号指示器,字节码解析器的工作是通过改变这个计数器的值,来选取下一条需要执行的字节码指令,分支、循环、跳转、异常处理、线程恢复等基础功能,都需要依赖这个 计数器来完成,几乎不发生内存溢出。
4. 本地接口(Native Interface)
作用:使得Java代码可以调用C、C++等本地语言编写的代码和库,提供了Java与操作系统交互的能力。
JVM通过这些组成部分协同工作,实现了Java程序的跨平台运行、内存管理、类加载与链接、代码执行与优化等功能。
二、 运行机制
Java程序的运行机制可以概括为以下几个步骤,这一过程体现了Java“编写一次,到处运行”的特性:
1. 源代码编写
描述:开发者使用Java语言编写源代码文件,通常以.java作为文件扩展名。
2. 编译
描述:使用Java编译器(javac)将源代码编译成字节码(.class文件)。字节码是一种中间语言,与硬件平台无关,是Java实现跨平台的关键。
产物:生成的字节码文件可以在任何支持Java的平台上运行。
3. 类加载
描述:当程序运行时,JVM的类加载器负责查找并加载所需的类字节码文件到内存中。这个过程包括了加载、验证、准备、解析和初始化几个阶段。
类加载器:主要涉及启动类加载器、扩展类加载器、系统类加载器及可能的自定义加载器。
4. 字节码校验
描述:为了保证安全性和合规性,JVM会对加载的字节码进行验证,检查其是否符合Java语言规范,防止非法操作。
5. 执行引擎执行
解释执行:JVM的解释器逐条解释并执行字节码指令。
即时编译(JIT):对于频繁执行的热点代码,JVM的即时编译器会将其编译成本地机器码,直接执行,提高执行效率。
6. 内存管理
堆和栈:对象实例存储在堆中,栈则保存方法调用信息和局部变量。JVM自动管理内存分配和回收,包括垃圾收集机制来回收不再使用的对象所占的内存。
7. 垃圾回收(Garbage Collection, GC)
描述:JVM自动进行垃圾回收,释放不再使用的对象占用的内存,减轻了程序员手动管理内存的负担。
8. 本地方法调用
描述:Java程序可以通过JNI(Java Native Interface)调用本地库中的函数,实现与操作系统或其他语言编写的代码的交互。
9. 程序结束
描述:当程序执行完毕或因异常终止时,JVM会进行资源清理,包括关闭线程、释放内存等操作。
整个过程体现了Java语言的跨平台特性和自动内存管理的优势,简化了开发和部署流程。
运行机制与类加载同源,只是描述的方向不一样,运行机制包含类加载过程。java类加载过程参考:java的类加载过程_java 类加载是首次使用才会加载吗-CSDN博客