Java面试被问:跟我讲下JVM和JMM?

面试官:你给我讲下JVM 跟JMM?

面试者:JVM就是我们的虚拟机,然后JMM我记得是并发编程如何保证数据可见性跟有序性。

面试官:具体点呢?

面试者:诶......

我来给你讲下吧:

先说 JVM(Java虚拟机)

JVM在跑起来的时候,会把操作系统给它的内存,划分成几个关键区域,每个地方放不同的东西,并且针对这些区域进行清理维护:

堆 你 new 出来的所有对象和数组 ,几乎都放在这里。它是垃圾回收器主要打扫的区域 。这是最大、最重要的一块 ,所有线程共享。

还有像 方法区(JDK8后叫元空间) 也是所有线程共享 。这里存放加载的类信息、常量、静态变量这些"模板"性质的东西。

还有线程私有的 虚拟机栈 本地方法栈 程序计数器等等

简单总结JVM: 它是个具体的执行引擎和内存管理者,负责把Java代码跑起来,管着内存的"物理"划分------哪里放对象、哪里放局部变量、垃圾怎么清理。

但是有个问题。上面提到的"堆"是共享的,意味着所有线程都能去访问里面的对象。但现代计算机为了快,CPU有高速缓存,编译器和处理器还会优化指令顺序(指令重排序)。这就会导致三个核心问题:

可见性问题 、有序性问题、 原子性问题

JMM(Java Memory Model), Java 内存模型就是为了定义一套规则,来解决这些问题。

JMM规定所有变量都存储在主内存(可以粗略理解为堆)中,每个线程有自己的工作内存(涵盖了缓存、寄存器等)。线程不能直接读写主内存,只能操作自己工作内存中的副本,然后再同步回主内存。

关键在于它定义的 happens-before 规则和提供的关键字:

happens-before 规则 是判断操作是否"可见"的核心原则,就是如果A操作 happens-before B操作,那么A做的所有改动,对B来说都是一定可见的。常见规则包括:程序顺序规则、监视器锁规则、传递性规则等等

然后就是几个关键字:

  • synchronized:当你要进入同步块时,JMM要求你先清空工作内存,从主内存重新加载变量。退出时,必须把修改过的变量刷回主内存。这样,就同时保证了原子性、可见性和有序性。
  • volatile:它保证两件事:1)每次读都从主内存读,每次写都立刻刷回主内存(保证可见性 )。2)禁止指令重排序(保证有序性 )。但它不保证原子性。
  • final:被final修饰的字段,一旦在构造器中初始化完成,并且构造过程没有"this"引用逸出,那么其他线程就能看到它的正确值。

总结下

  • JVM是"实现者"和"平台" 。它具体负责内存怎么划分(堆、栈...),代码怎么执行,垃圾怎么回收。它是一个运行时实例。
  • JMM是"规范"和"契约" 。它定义了在多线程这个特定场景下,数据应该如何被访问和同步,以保证正确性。它是一套规则。

所以,JVM管的是"程序怎么跑",JMM管的是"多线程环境下,怎么跑才对"。

相关推荐
小小张说故事14 小时前
Python 的 str 为什么设计成不可变?拆开字符串驻留、字符串池,以及 += 拼接到底慢在哪
后端·python
AI架构师之家14 小时前
我把 Hermes 这匹"马"养了两周,它干了一件让我有点发毛的事
后端
dpharness15 小时前
块协议用了两周,我把九个坑按顺序记下来了
后端
加宝的起点雷达15 小时前
跑了两周的信号日报,我把降级链改了四次
人工智能·后端
IT枫斗者枫哥15 小时前
CompletableFuture失败后返回空列表:异常没了,业务含义也变了
java·后端
Gopher_HBo15 小时前
opentelemetrySDK源码解析
后端
UrbanJazzerati15 小时前
AutoHotkey v2 零基础快速入门 Part 10:给路线回放添加高精度计时,理解累计延迟与路线一致性
后端
70后写java的老码农15 小时前
Spring Boot 3 + ShardingSphere-JDBC 实战:一次把读写分离和分库分表跑通
后端
泡海椒15 小时前
04-饼图评级构成-信用评级构成
后端
知守观15 小时前
多模块架构演进:横向分层 vs 纵向领域,13 个真实项目的切分对照
java·后端·微服务