为了更清晰地对比JVM和JMM,我们可以采用表格形式,从定义、功能、结构、与多线程关系等方面进行详细比较:
对比项 | JVM(Java Virtual Machine) | JMM(Java Memory Model) |
---|---|---|
定义 | 一种虚构的计算机,为Java程序提供与底层操作系统和硬件无关的运行环境,实现“一次编写,到处运行” | 一种抽象规范,定义了Java程序中多线程访问共享内存的规则 |
主要功能 | - 字节码执行:加载并将字节码解释或编译成机器码执行 - 内存管理:管理堆、栈、方法区等运行时内存 - 垃圾回收:自动回收不再使用的对象内存 | - 解决多线程内存可见性问题:确保一个线程对共享变量的修改能及时被其他线程看到 - 保证原子性操作:确保操作不可中断,要么全执行,要么全不执行 - 处理指令重排序:防止因指令重排序导致多线程程序出错 |
结构组成 | - 类加载子系统:负责加载字节码文件 - 运行时数据区:包含堆、栈、方法区等 - 执行引擎:执行字节码指令 | 围绕主内存与工作内存的交互规则,以及保证原子性、可见性、有序性的规则体系 |
与多线程关系 | 为多线程提供运行的基础环境,管理多线程的内存分配和线程调度等 | 专门针对多线程环境,确保多线程对共享内存的访问符合规则,避免数据竞争和并发问题 |
作用层面 | 从整体上保障Java程序的运行,涵盖编译、执行、内存管理等各个方面 | 专注于多线程场景下的内存访问控制,确保多线程程序的正确性和稳定性 |
实现方式 | 通过具体的软件实现,如HotSpot JVM,包含一系列复杂的算法和数据结构来实现其功能 | 通过制定内存访问规则,依赖关键字(如volatile 、synchronized )和同步机制来实现 |
-
JVM(Java Virtual Machine,Java虚拟机)
- 定义与概念:JVM是Java程序的运行核心,它是一种虚构出来的计算机,通过在实际的计算机上仿真模拟各种计算机功能来实现的。它为Java程序提供了一个与底层操作系统和硬件无关的运行环境,使得Java程序能够实现“一次编写,到处运行”的特性。
- 主要功能:
- 字节码执行:Java源文件经过编译器编译后生成字节码文件(
.class
文件)。JVM负责加载字节码文件,并将字节码解释或编译成机器码,然后在计算机上执行。例如,当我们运行一个简单的Java程序HelloWorld
,JVM会加载HelloWorld.class
文件,将其中的字节码转化为机器可执行的指令。 - 内存管理:JVM管理Java程序运行时的内存,包括堆内存、栈内存、方法区等。堆内存用于存储对象实例,栈内存用于存储方法调用和局部变量等。比如,当创建一个
new ArrayList()
对象时,该对象会被分配到堆内存中,而调用创建该对象方法的相关局部变量会存储在栈内存中。 - 垃圾回收:JVM自带垃圾回收机制(Garbage Collection,GC),它自动回收不再被使用的对象所占用的内存空间,减轻了程序员手动管理内存的负担。例如,当一个对象不再有任何引用指向它时,垃圾回收器会在适当的时候回收该对象占用的堆内存。
- 字节码执行:Java源文件经过编译器编译后生成字节码文件(
- 结构组成:
- 类加载子系统:负责加载字节码文件到JVM中。它通过不同的类加载器(如启动类加载器、扩展类加载器、应用程序类加载器)按照一定的层次结构来加载类,保证类的唯一性和安全性。
- 运行时数据区:包含上述提到的堆、栈、方法区等不同的内存区域,每个区域有其特定的功能和用途。
- 执行引擎:负责执行字节码指令,将字节码翻译为对应平台的机器码。执行引擎可以采用解释执行(逐行解释字节码)或者即时编译(JIT,将热点代码编译成本地机器码以提高执行效率)等方式。
-
JMM(Java Memory Model,Java内存模型)
- 定义与概念:JMM是一种抽象的规范,它定义了Java程序中多线程访问共享内存的规则。它描述了在JVM中,各个线程如何访问和修改共享变量,以及如何保证不同线程之间对共享变量操作的可见性、原子性和有序性。
- 主要功能:
- 解决多线程内存可见性问题:在多线程环境下,一个线程对共享变量的修改,其他线程何时能看到是不确定的。JMM通过规定线程对共享变量的读写操作与主内存之间的交互规则,来保证内存可见性。例如,使用
volatile
关键字修饰的变量,当一个线程修改了这个变量的值,会立即刷新到主内存,其他线程读取时会从主内存获取最新值。 - 保证原子性操作:原子性指一个操作是不可中断的,要么全部执行成功,要么全部不执行。JMM定义了一些基本操作的原子性,如对基本数据类型(除
long
和double
在某些平台上)的简单读写操作是原子的。对于复合操作,如i++
,可以通过synchronized
关键字或Atomic
类来保证原子性。 - 处理指令重排序:为了提高性能,编译器和处理器可能会对指令进行重排序。JMM通过一些规则来确保在多线程环境下,指令重排序不会导致程序出现错误的执行结果。例如,
volatile
关键字不仅保证可见性,还能禁止指令重排序,确保volatile
变量的读写操作顺序与代码顺序一致。
- 解决多线程内存可见性问题:在多线程环境下,一个线程对共享变量的修改,其他线程何时能看到是不确定的。JMM通过规定线程对共享变量的读写操作与主内存之间的交互规则,来保证内存可见性。例如,使用
- 与多线程的关系:JMM是为了保证多线程环境下程序的正确性和稳定性而设计的。它为多线程编程提供了内存层面的规范,使得程序员可以基于这些规则编写线程安全的代码。例如,当多个线程同时访问和修改共享资源时,通过遵循JMM的规则,使用合适的同步机制(如
synchronized
、Lock
等),可以避免数据竞争和其他并发问题。
-
JVM与JMM的关系
- JMM是JVM的一部分:JMM是JVM规范中关于内存访问规则的部分,它是JVM整体架构中负责多线程内存管理和同步的模块。
- JVM为JMM提供运行基础:JVM提供了运行时数据区(包括主内存和工作内存等概念),这些是JMM规则得以实施的基础。JVM的类加载、执行引擎等子系统与JMM相互配合,共同保证Java程序在多线程环境下的正确运行。例如,执行引擎在执行字节码指令时,需要遵循JMM关于内存访问的规则,确保多线程操作共享变量的正确性。