JVM 遇到的问题-1.0

JVM 遇到的问题-1.0

Q1. java 虚拟机规范定义的运行时数据区有几块?分别是什么?

A :一共有5块

B分别是:程序计数器,java 堆,java虚拟机栈,本地方法栈,方法区(jdk8之后改成元空间)。

⚠️ 注意事项

1). 直接内存不属于运行时数据区;

2). jdk7之前方法区实现为永久代PermGen,jdk8之后彻底移除永久代,使用元空间。

3). 程序计时器是唯一没有OOM的内存区域。

Q2.直接内存是什么?又叫什么?

A: 直接内存又称为堆外内存。通过Unsafe向操作系统直接申请的内存,

典型 API:ByteBuffer.allocateDirect(),Netty 大量使用堆外缓冲区。存放 NIO 网络 IO 的数据缓冲区;不在 Java 堆中,不受-Xmx/-Xms限制。

⚠️ 注意事项

  1. 堆上只会生成一个很小的DirectByteBuffer代理对象,真实数据存在堆外;
  2. 依靠Cleaner虚引用异步回收,极易发生堆外内存泄漏;
  3. 调控参数:-XX:MaxDirectMemorySize;OOM 报错:Direct buffer memory。

Q3:JVM 的组成 = 运行时数据区 + 直接内存?

A:这样说,表述不严谨,是不对的。JVM 完整的架构是五大子系统:

类加载子系统,运行时数据区,执行引擎,gc子系统,本地方法接口。

B: 从进程内存占用视角看,JVM 进程使用的内存包含:运行时数据区 + 直接内存。直接内存不属于 JVM 规范定义的运行时数据区,只是排查内存故障时需要一并分析。

Q4:如何系统掌握各区域 OOM 场景,并且动手复现?

1)熟记映射表:异常日志 → 定位内存区域

|------------------------------------|-----------|
| 报错信息 | 对应区域 |
| Java heap space | Java 堆 |
| Metaspace | 元空间 (方法区) |
| Direct buffer memory | 直接内存 |
| unable to create new native thread | 虚拟机栈 |
| StackOverflowError | 虚拟机栈 |

2)每一个 OOM Demo 强制配套 3 组 JVM 参数

|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Plain Text # 1. GC日志输出 -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -Xloggc:gc.log # 2. OOM自动dump堆快照 -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=oom.hprof # 3. 限制对应区域内存,稳定复现 |

3)分层练习

① 基础 Demo 复现(while 循环简易案例)

② 模拟业务真实内存泄漏(ThreadLocal、静态缓存、动态类)

③ 使用 MAT 分析 hprof 快照,定位引用链,区分【内存泄漏 / 单纯内存不足】

Q5:OOM 发生之后,JVM 进程一定会退出吗?

A:不一定。

如果代码捕获 OOM 异常,当前线程终止,其他线程可继续运行;持续分配对象会反复抛出 OOM,进程不会直接死掉。

Q6:StackOverflowError 和 OOM 的本质区别?

A:

  • StackOverflowError:单个线程栈空间容量不足,方法调用层级过深;
  • unable to create new native thread OOM:系统资源不足,无法新建线程分配栈内存

Q7:发生堆 OOM,一定是堆太小吗?

A:不一定。两种场景:

  1. 业务流量变大,对象总量上升 → 需要调大堆;
  2. 代码内存泄漏,无用对象持续占用 → 改代码,单纯调堆治标不治本。

Q8:为什么 Netty 优先使用直接内存?

A:减少一次内核缓冲区与 JVM 堆缓冲区的数据拷贝(减少一次内存复制,零拷贝思想,提升 IO 性能);代价是堆外内存管理复杂,容易泄漏。

Q9:程序计数器为什么不会产生 OOM?

A:每条线程的程序计数器只保存一条指令地址,内存占用极小;JVM 规范明确规定此区域不需要回收,不会出现内存溢出。

相关推荐
Flynt3 小时前
Java 27 升级实测:默认值动得比新特性多,有个老参数会让 JVM 直接起不来
java·jvm·后端
用户094248568038 小时前
第10章:OpenJDK异常体系、栈轨迹与错误诊断入门
java·jvm
杨杨杨大侠9 小时前
Java 不再需要 JVM?一文看懂 GraalVM Native Image、Substrate VM 与 JDK
java·jvm·java ee
顺风尿一寸16 小时前
从 ls -U 到 Tomcat libs加载jar包:ext4 目录哈希序如何影响 Java 文件排序顺序
linux·jvm
刘天远17 小时前
Agent最小权限实现:策略表、临时令牌与撤权回归
java·jvm·人工智能·sqlite
用户094248568031 天前
第9章:OpenJDK堆分代与 Serial/Parallel GC 基础
java·jvm
小陈不好吃1 天前
深入理解 JVM 内存模型:从堆栈结构到 GC 日志分析实战
java·jvm·java-ee·jdk
liangbo72 天前
12-JVM 调优方法论与参数速查
java·jvm
用户094248568032 天前
第8章:Java 内存模型(JMM)入门——可见性、有序性、原子性
java·jvm
西峰u2 天前
Java多线程从入门到线程安全
java·开发语言·jvm