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 规范明确规定此区域不需要回收,不会出现内存溢出。

相关推荐
香蕉大香蕉(06敬畏市场)1 天前
高频八股 · Java 并发编程(10):异步、ThreadLocal 与虚拟线程(收官)
java·开发语言·网络·jvm·python·ai·实习
wuminyu1 天前
JVM规范学习总结-Class文件结构
java·linux·c语言·jvm·c++
酌沧2 天前
MemT让记忆成为模型内生能力
jvm·人工智能·算法
wuminyu3 天前
JVM规范学习总结-Java源码经过javac编译后产物
java·linux·c语言·jvm·c++
学到老活到老3 天前
类已经加载了,为什么静态代码还没执行?
java·jvm
学到老活到老3 天前
写了 new,就一定会在堆上分配对象吗?
java·jvm
笨笨饿3 天前
# 59_CSDN博客自动写流程文章
linux·jvm·stm32·单片机·嵌入式硬件·mcu·51单片机
tedcloud1233 天前
Docker Compose 部署 Memos:从安装到备份恢复
linux·开发语言·jvm·后端·docker·容器·rust
螺蛳粉 螺蛳粉3 天前
大数据第四篇:事故复盘:移走 HBase 里 27 个 hadoop-2.10.2 jar 后,HMaster 半小时后“自杀“了【jar 事故复盘】
jvm·hadoop·hbase·异常处理·大数据运维·踩坑记录·事故复盘
wuminyu4 天前
JVM规范学习总结-JVM规范基本概念
java·linux·c语言·jvm·c++