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

面试官:你给我讲下JVMJMM

面试者: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管的是"多线程环境下,怎么跑才对"。

相关推荐
devlei3 小时前
从源码泄露看AI Agent未来:深度对比Claude Code原生实现与OpenClaw开源方案
android·前端·后端
努力的小郑4 小时前
Canal 不难,难的是用好:从接入到治理
后端·mysql·性能优化
Victor3565 小时前
MongoDB(87)如何使用GridFS?
后端
Victor3565 小时前
MongoDB(88)如何进行数据迁移?
后端
小红的布丁5 小时前
单线程 Redis 的高性能之道
redis·后端
GetcharZp5 小时前
Go 语言只能写后端?这款 2D 游戏引擎刷新你的认知!
后端
宁瑶琴7 小时前
COBOL语言的云计算
开发语言·后端·golang
普通网友7 小时前
阿里云国际版服务器,真的是学生党的性价比之选吗?
后端·python·阿里云·flask·云计算
IT_陈寒8 小时前
Vue的这个响应式问题,坑了我整整两小时
前端·人工智能·后端
Soofjan9 小时前
Go 内存回收-GC 源码1-触发与阶段
后端