6. 后端开发常见 JVM 问题

本文我们将探讨:后端开发常见 JVM 问题与排查工具

作为后端开发人员,我们在生产环境中总会遇到程序崩溃、卡顿或者服务器 CPU 飙高的情况。在本文中,我们将分析最常见的两个内存溢出错误,以及如何使用 JDK 自带的四大常用排查命令来进行问题定位。

1. 内存溢出(OOM - Out Of Memory)

当 JVM 需要给数据分配内存,却发现整个内存区域已经全被占满,且垃圾回收器(GC)拼尽全力也清理不出任何空间时,JVM 就会抛出 java.lang.OutOfMemoryError 错误,程序随后就会崩溃挂掉。

生产环境中最常遇到的有两种 OOM:

① 堆内存溢出(java.lang.沉没/OutOfMemoryError: Java heap space

  • 为什么发生:我们在第三部分讲过,堆是存放对象实体的地方。如果你不断创建对象,且这些对象由于被某些长寿对象(如静态集合、全局 Service)引用而无法被 GC 回收(即发生了内存泄漏),堆内存迟早会被耗尽。
  • 后端常见场景
    • 一次性查询了太多数据:比如写了一条没有加 LIMIT 分页的 SQL,直接把数据库里几百万条用户数据一次性查出来放到了一个 List 里面,堆内存瞬间被撑爆。
    • 死循环创建对象:代码里写了死循环,不停地 new 对象并往一个全局 Map 里塞。

② 元空间溢出(java.lang.OutOfMemoryError: Metaspace

  • 为什么发生:元空间存放的是类的信息(设计图纸)。如果程序在运行期间,不断加载了成千上万个新的类,元空间就会爆掉。
  • 后端常见场景
    • 很多现代框架(如 Spring 的某些动态代理机制)会在运行期间动态生成类。如果框架使用不当,或者引入了某些会无限生成动态类的第三方库,就会导致元空间溢出。

2. JDK 自带的四大核心排查命令

当线上服务器的 Java 程序突然变慢,或者直接崩掉时,我们不能盲目猜原因。JDK 在安装时就已经自带了一套命令行小工具,可以帮我们直接看穿 JVM 内部的现状。

假设我们已经通过 Linux 的 top 命令找到了那个出问题的 Java 程序的进程 ID(假设是 12345)。接下来就可以派出这四大金刚:

jps(Java Virtual Machine Process Status Tool)

  • 作用:查看当前计算机上运行了哪些 Java 进程。
  • 怎么用:直接输入 jps -l。它会列出所有正在运行的 Java 程序的进程 ID 和它们的主类全名。有了进程 ID,你才能用接下来的其他工具。

jstat(JVM Statistics Monitoring Tool)

  • 作用:实时监控 JVM 的内存和垃圾回收(GC)情况。
  • 怎么用:输入 jstat -gcutil 12345 1000(表示每隔 1000 毫秒打印一次进程 12345 的内存使用占比)。
  • 看什么:你可以清晰地看到年轻代(Eden、Survivor)、老年代的内存占比。如果发现老年代占比一直是 99% 且伴随着 Full GC 次数疯狂暴涨,说明程序已经离 OOM 不远了。

jstack(Stack Trace for Java)

  • 作用:抓取当前的线程栈快照
  • 解决什么问题:当服务器的 CPU 占用率突然飙到 100%,或者程序出现了死锁(A 线程等 B,B 线程等 A,大家都动弹不了)时,用 jstack 12345 打印出所有线程正在执行的代码行数。你可以直接看到是哪一行代码把 CPU 跑满了,或者哪几个线程卡在了锁上面。

jmap(Memory Map for Java)

  • 作用:生成堆内存快照文件(Dump 文件)
  • 解决什么问题:当程序发生 OOM 崩溃,或者你怀疑有内存泄漏时,可以用 jmap -dump:format=b,file=heap.hprof 12345 把这一刻堆内存里所有的对象数据打包下载下来。然后你可以把这个 heap.hprof 文件导入到图形化分析工具(如 MAT 或 JProfiler)中,工具会直观地告诉你:到底是谁霸占了几个 G 的内存不撒手。

总结

到这里,我们已经完整地了解了 JVM 的核心知识体系:

  • 知道了它通过字节码和各系统专属的 JVM 实现了跨平台
  • 拆解了它内部的四大核心架构五大内存区域
  • 理解了对象如何在年轻代老年代之间流转,并被 GC 清理。
  • 搞懂了类进入内存的双亲委派机制
  • 最后掌握了后端如何面对 OOM 以及用什么排查工具进行定位与排查

掌握了这些 JVM 的核心机制和排查手段,我们就能够在日常的后端开发中更加游刃有余地应对各种线上问题。

一个敲代码的