程序跑了一段日子,发现内存突然增高,妥妥的占满了4个G。查看日志,发现有大量的错误:
a、Rabbitmq消费错误:
o.s.a.r.l.SimpleMessageListenerContainer : Consumer thread error, thread abort.
b、redis发序列化错误:
org.springframework.core.serializer.support.SerializationFailedException: Failed to deserialize payload. Is the byte array a result of corresponding serialization for DefaultDeserializer?; nested exception is java.lang.OutOfMemoryError: GC overhead limit exceeded
c、大量的java.lang.OutOfMemoryError: Java heap space
根本原因都是由于Java heap space而起。那就需要立即获得内存快照。还好在程序启动时候添加了参数:-XX:+HeapDumponOutOfMemoryError -XX:HeapDumpPath=heapdum.hprof
p 当发生OOM的时候,自动转储内存快照。如果启动时候没加这个参数,则通过jmap获取当前内存快照,分析是谁占据了内存没有释放:
jmap -dump:format=b,file=heap.hprof
jmap是一个可以输出所有内存中对象的工具,可以将VM中的heap,以二进制输出成文本。打印出某个java进程中的内存使用情况(如:产生对象,及其数量,占用空间)。
file:保存路径及文件名
pid:进程编号(ps aux查看)
(强制Full GC:jmap -histo
获得了内存快照,接下来就是如何查看了,用到了两个工具,java自带的jvisualvm和破解的JProfiler(需要的留言吧),接下来主要讲解超级无敌强大的JProfiler(完美的定位了内存泄露的对象以及引用)。不但可以分析内存快照文件,还可以分析当前环境运行中的java进程。
a、安装破解方法请自行搜索(需要的私信或留言)。
b、使用JProfiler打开快照文件:
发现byte[]占用了3.6G的空间。
在对象上右键
选择Incoming后,点击ok,可以看到有的byte[]几乎上G,已经超级无敌大
打开第一个byte[],查看引用该对象的对象,发现是一个变量中保存了该对象。
既然已经定位到了变量,查看代码后发现,该byte[]数组意外产生,所以并没有清除机制。导致了Java heap space



