千万别搞混了,JMM和JVM的本质区别(分工、作用、目的)

117 阅读4分钟

知其然要知其所以然,探索每一个知识点背后的意义,你知道的越多,你不知道的越多,一起学习,一起进步,如果文章感觉对您有用的话,关注、收藏、点赞,有困惑的地方可以评论,我们一起探讨!

1、定义

Java 内存模型(JMM)

Java 内存模型是一种抽象的概念,它是由 Java 语言规范定义的一组规则和协议,目的是为了屏蔽各种硬件和操作系统的内存访问差异,以保证 Java 程序在不同的平台上都能达到一致的内存访问效果。它主要关注的是多线程环境下,不同线程之间的共享变量的可见性、有序性以及原子性问题。

JVM 内存区域

JVM 内存区域是指 Java 虚拟机在运行时将其所管理的内存划分成的不同的数据区域,这些区域有着不同的用途、创建和销毁时间。它是实实在在的内存划分,包括程序计数器、虚拟机栈、本地方法栈、Java 堆、方法区等具体的内存区域。

2、作用

Java 内存模型(JMM)

  • 保证内存可见性:确保一个线程对共享变量的修改能够及时被其他线程看到。例如,当一个线程修改了某个共享变量的值,JMM 会保证其他线程在合适的时候能够看到这个修改后的值,避免出现数据不一致的问题。
  • 保证有序性:通过禁止特定类型的指令重排序,保证程序在多线程环境下的执行结果符合预期。指令重排序是指编译器和处理器为了提高性能而对指令进行重新排序的优化手段,但在多线程环境下可能会导致程序出现错误,JMM 会对其进行一定的限制。
  • 保证原子性:对于一些基本的操作(如对变量的读写操作)提供原子性保证,避免出现数据竞争的问题。

JVM 内存区域

  • 程序计数器:作为当前线程所执行的字节码的行号指示器,帮助字节码解释器选取下一条需要执行的字节码指令,实现代码的顺序执行、分支、循环等操作。
  • 虚拟机栈:描述 Java 方法执行的内存模型,每个方法执行时会创建栈帧,用于存储局部变量表、操作数栈、动态链接、方法出口等信息。
  • 本地方法栈:为虚拟机使用的本地(Native)方法服务,与虚拟机栈类似。
  • Java 堆:是对象实例分配的主要区域,几乎所有的对象实例都在这里分配内存,同时也是垃圾收集器管理的主要区域。
  • 方法区:用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。

3、关注重点

Java 内存模型(JMM)

主要关注多线程之间的内存交互和同步问题,通过定义一系列的规则来保证多线程程序的正确性和一致性。它解决的是在多线程环境下,如何保证不同线程对共享变量的访问是安全和有序的。

JVM 内存区域

主要关注内存的划分和使用,不同的内存区域有不同的用途和管理方式。它解决的是 Java 程序在运行过程中,如何合理地分配和管理内存资源,以提高程序的性能和稳定性。

4、示例代码说明

Java 内存模型示例

public class JMMExample {
    private static boolean flag = false;
    private static int number = 0;

    public static void main(String[] args) {
        // 线程1
        Thread t1 = new Thread(() -> {
            while (!flag) {
                // 空循环
            }
            System.out.println(number);
        });

        // 线程2
        Thread t2 = new Thread(() -> {
            number = 42;
            flag = true;
        });

        t1.start();
        t2.start();
    }
}

在这个示例中,如果没有 JMM 的保证,线程 1 可能永远看不到 flag 的修改,从而陷入无限循环。JMM 通过内存屏障等机制保证了线程之间的可见性。

JVM 内存区域示例

public class JVMMemoryAreaExample {
    private static int staticVariable = 10; // 存储在方法区

    public static void main(String[] args) {
        int localVariable = 20; // 存储在虚拟机栈的栈帧中
        Object obj = new Object(); // obj 引用存储在虚拟机栈,对象实例存储在 Java 堆
    }
}

这个示例展示了不同类型的变量在 JVM 内存区域中的存储位置。

5、总结

Java 内存模型和 JVM 内存区域是两个不同层面的概念。Java 内存模型关注的是多线程环境下的内存交互和同步,是一种抽象的规则和协议;而 JVM 内存区域关注的是内存的具体划分和使用,是实实在在的内存区域。理解它们的区别有助于我们更好地编写高效、安全的 Java 程序。