Debian上的Java错误排查可以通过以下几种技巧进行:
-
确认错误类型:
- 通过错误日志明确内存溢出区域,例如
java.lang.OutOfMemoryError: Java heap space
表示堆内存溢出,java.lang.OutOfMemoryError: Metaspace
表示元空间溢出等。
-
通用排查步骤:
- 获取关键信息:包括错误日志、JVM参数(如堆大小
-Xms
/-Xmx
、元空间大小 -XX:MetaspaceSize
)和系统监控(如 top
、jstat
或 APM 工具)。
- 生成内存快照:
- 自动生成堆转储:添加JVM参数
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/path/to/dump.hprof
。
- 手动生成堆转储:使用
jmap
命令:jmap -dump:format=b,file=/path/to/dump.hprof <pid>
。
- 分析堆转储:
- 使用工具如 Eclipse MAT (Memory Analyzer Tool) 查找 Dominator Tree,确认占用内存最大的对象。
- 使用 VisualVM 查看对象实例数量和引用链。
- 使用 JProfiler(商业工具)实时监控内存分配和对象存活情况。
-
分场景排查:
- 堆内存溢出(Heap Space):
- 排查重点:是否存在内存泄漏或数据量激增。
- 关注全局缓存、线程池任务队列、第三方库等。
- 在 MAT 中按 Retained Heap 排序,找到占用最高的对象,并进行代码审查。
- 元空间溢出(Metaspace):
- 排查重点:类加载器泄漏或动态类生成未卸载。
- 使用
jmap -clstats <pid>
查看类加载器统计信息。
- 检查加载的类数量,并进行代码审查。
- 直接内存溢出(Direct Buffer):
- 排查重点:NIO操作或第三方库(如 Netty)未释放堆外内存。
- 增大
-XX:MaxDirectMemorySize
,确保 ByteBuffer.allocateDirect()
后调用 System.gc()
或手动释放。
- 监控堆外内存,并进行代码审查。
- 线程数超限(Unable to create native thread):
- 排查重点:线程泄漏或操作系统限制。
- 检查线程池是否复用,第三方库是否未限制连接数。
- 查看线程数,并进行代码审查。
-
处理 java.lang.OutOfMemoryError: Kill process (java) or sacrifice child
:
- 原因:系统级内存不足,常见诱因包括设备上运行的进程过多、初始堆大小和最大堆大小设置不同、本地内存区域增长、应用程序内存泄漏等。
- 解决方法:
- 增加 RAM 容量。
- 减少其他进程。
- 将初始堆大小和最大堆大小设置为相同值。
- 修复本地内存泄漏。
- 限制本地内存:通过
-XX:MaxDirectMemorySize
控制 Direct Buffer 大小。
- 排查方法:
- 查看内核日志:运行
dmesg -T
查看内核活动。
- 修复内存问题,确保上述解决方案得到实施。