外观
一句话答案
核心参数:-Xms/-Xmx(堆大小)、-XX:+UseG1GC(收集器)、-XX:MaxGCPauseMillis(目标停顿)、-XX:+HeapDumpOnOOM。
核心要点
线程共享(所有线程共同访问):
- 堆(Heap):对象实例存放在这里,多线程都可以访问 → 需要同步控制
- 方法区(Metaspace):类信息、常量池、静态变量 → 需要同步控制
线程私有(每个线程独立拥有):
- 虚拟机栈:每个线程有自己的栈,栈帧随方法调用入栈/出栈
- 本地方法栈:同上,服务 native 方法
- 程序计数器:记录线程自己的执行位置,线程切换时恢复
这是多线程内存可见性问题的根源:
- 线程 A 修改了堆上的共享对象,线程 B 不一定立即可见(CPU 缓存与主存不一致)
- Java 内存模型(JMM)通过
volatile、synchronized、happens-before规则来保证可见性
追问与易错
追问方向:
- -Xms 和 -Xmx 为什么建议设成一样?
- 怎么选择 GC 收集器?
- 你在生产环境设过哪些 JVM 参数?
易错点:
- ❌ 照搬网上参数不结合实际场景
- ❌ 忘记设 HeapDumpOnOOM
💡 记忆锚点
堆和方法区是公共财产(线程共享,需要锁来保护),栈和程序计数器是私人物品(线程私有,天然安全)。线程A改了公共财产B不一定看得到——这就是可见性问题的根源,解药是volatile/synchronized/happens-before。