整理自毕玄大神的ppt,结合工作中遇到的相关问题,扩充了部分细节,有一些问题还没有遇到过,整理下来,以备不时之需。
NoSuchMethodException
同类型问题有ClassNotFoundException
,NoClassDefFoundError
原因
java ClassLoader机制
jar版本冲突
排查方法
- 查看加载的类信息
-XX:+TraceClassLoading
-verbose:class
jar -tvf *.java
- 检查依赖冲突
mvn -U clean package -Dmaven.test.skip=true enforcer:enforce -DcheckDeployRelease_skip=true -Denforcer.skip=false
- 使用maven管理依赖,注意父子POM,正确使用
<dependencies>
与dependencyManagement
- 使用
<scope>provided</scope>
去除不需要的版本
Maven最佳实践
ClassNotFoundException
显示加载一个类通常有如下方式:
* 通过Class
的forName()
方法;
* 通过ClassLoader
中的loadClass()
方法;
* 通过ClassLoader
中的findSystemClass()
方法;
出现这个错误就是当JVM要加载指定文件的字节码到内存时,并没有在指定路径找到这个文件,需要检查当前classpath
下有没有这个文件,查看当前classpath
可以使用:
this.getClass().getClassLoader().getResource("").toString();
OOM
GC overhead limit exceed/java heap space
原因
java heap分配不出需要的内存了
TODO tu
排查方法
- 确定系统内存占用
free -m
- 拿到heap dump文件
-XX:+HeapDumpOnOutOfMemoryError
jmap -dump:file=<file name>,format=b [pid]
gcore [pid]
- 分析dump文件(MAT)
Java程序内存分析:使用mat工具分析内存占用
MAT - Memory Analyzer Tool 使用进阶
- 根据MAT分析结果定位代码(btrace)
BTrace工具简介
一次线上OOM过程的排查
类似的问题还有full gc频繁。
unable to create new native thread
原因
- 线程数超过了
ulimit
,会导致ps
等出现resource temporary unavailable
,可以临时调整ulimit
。
- 线程数超过了
kernel.pid_max
,只能重启
- 机器完全没有可用内存了
排查方法
ps -eLf | grep java -c
cat /proc/[pid]/limits
,如果太小,可以调大max open processes
的值
sysctl -a | grep kernel.pid_max
- 如果真是线程创建太多,如果有线程名比较好排查,推荐使用线程池,并限制大小,对使用的api要非常清楚,比如很容易误用的netty client
PermGen Space
原因
PermGen被占满
排查方法
- btrace ClassLoader.defineClass
- 确认是否需要装载这么多,如果是,则需要调大
PermGen
,如果不是,需要控制ClassLoader
,常用于Groovy的误用
direct buffer memory
堆外内存之 DirectByteBuffer 详解
java之HeapByteBuffer&DirectByteBuffer以及回收DirectByteBuffer
原因
direct byteBuffer使用超出了限制
解决方法
- 调整参数
-XX:MaxDirectMemorySize
- 通常由于网络通信未做限流,需要在业务层做限制
Map filed
原因
FileChannel mapped文件超出了限制
排查方法
- btrace FileChannel.map
- 看看是不是加了
-XX:+DisableExplicitGC
解决方法
- 如有必要调大
vm.max_map_cout
- 如map file存活个数其实不多,可以去掉
-XX:+DisableExplicitGC
,在CMS GC情况下,增加-XX:+ExplicitGCInvokesConcurrent
request {} bytes for {}. out fo swap space
原因
排查方法
-
btrace,Deflater.init |
Deflater.end |
Inflater.init |
Inflater.end |
- 强行执行full gc
解决方法
- 地址空间不够,升级到64位
- 物理内存耗光,Inflater/Deflater问题的话显示调用end
- DirectByteBuffer问题可以调小-XX:MaxDirectMemorySize
- 其他case根据google perftools显示的来跟进
CPU us高
原因
- CMS gc/full gc频繁
- 代码中出现非常耗CPU操作
排查方法
- jstack,top待补充
- gc log
CPU sy高
原因
- 锁竞争激烈
- 线程主动切换频繁
- linux 2.6.32 后的高精度问题
排查方法
jstack
看锁状态
- 是不是有主动线程切换
- btrace,AbstractQueuedSynchronizer.ConditionObject.awaitNanos
解决方法
- 锁竞争激烈,根据业务实现要求合理做锁力度控制,或引入无锁数据结构
- 线程主动切换,改为通知机制
- 高精度问题,至少调大到1ms+的await
CPU iowait高
原因
io读写操作频繁
排查方法
- 确认硬件状况,例如RAID的cache策略
- 借助系统工具,blktrace+debugfs,iotop,btrace
解决方法
- 提升dirty page cache
- cache
- 同步写转异步写
- 随机写转顺序写
- 升级硬件
java进程退出
原因
原因很多
排查方法
- 查看生成的
hs_err_pid[pid].log
- 确保
core dump
已打开,cat /proc/[pid]/limits
dmesg | grep -i kill
- 根据
core dump
文件分析,gdb [java路径] core文件
死锁
jstack -l
分析线程堆栈信息
线程池耗光
增加线程数,减少超时时间
调用另一服务超时
可能原因:
* 服务端响应慢
* 服务端或客户端GC频繁
* 服务端或客户端CPU消耗严重
* 反序列化失败
* 网络问题
总结