# OOM 的原因
# 申请了大量的对象
写查询语句,不加 limit, 直接查到全表了
<select>
select id, name, .... from user
<where>
<if test='name !=null && name!='''>
name = #{name}
</if>
</where>
</select>
当 name 等于 null 或者空字符串时,直接变成了查全表,有条军规就是查询必加 limit
# 内存用尽,资源不释放
Map 一直存,不做容量控制。定时任务最常见,要么是忘了 clear (), 要么就是没有设置 lru 之类的淘汰算法.
还有就是 IO 对象不释放,记得调用 close () 呀
文件的话,记得调用 close (), 或者用 try-resource 语法糖
如果是连接对象的话,可以用连接池,保证下限
# 服务器内存真的低
我们的开发环境,单台只给了 16G, 感觉数据多一点,就卡的不行
可以用命令看下当前 堆的状态
jmap -heap
# 定位方法
# 先看一眼 当前已经有的日志文件,业务日志和 GC 日志
先估摸的看下,OOM 出现,一般都是话务量场景,有大量请求,这第一点属于是能看出来就好,看不来就算了
# 分析 dump 文件
为啥没有优先用这个方法呢,因为现网都是 jre, 没有 jdk, 一般也咩有加上堆转储的启动参数,没有现成的 dump 文件
这里分两种情况
- 开启了堆转储参数,且 oom 已发生,这时候 JVM 会自动给生成 dump 文件
java -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=~/dumps/java_heapdump.hprof -jar test.jar -XX:+HeapDumpOnOutOfMemoryError:当发生OutOfMemoryError时,生成堆转储文件。 -XX:HeapDumpPath=~/dumps/java_heapdump.hprof
- 没有开启堆转储参数,那只能用命令了
jmap -dump:format=b,file=test.hprof 1234 jamp -dump:format=b,file=[文件名] [pid] pid 用jsp 或者 ps -ef | grep java
# dump 文件分析
说实话挺简单的,把 dump 文件下载到本地,用 visualvm 载入,就看哪个类占用最多就可以了,排除掉 char [] 和 String
如果程序里面咩有用自定义类,而全用 Map 的,可以动手打人了,所以说有条军规就是让别用 Map 来,弄贼多魔法值 Key, 维护和定位都麻烦.
Map 的情况真的很难定位,排除 Map