您的位置:首页 > 健康 > 养生 > 免费企业网站建设要求_我们的服务理念和价值观_百度推广代理加盟_东莞网络优化排名

免费企业网站建设要求_我们的服务理念和价值观_百度推广代理加盟_东莞网络优化排名

2024/10/31 7:09:42 来源:https://blog.csdn.net/Muscleheng/article/details/142958806  浏览:    关键词:免费企业网站建设要求_我们的服务理念和价值观_百度推广代理加盟_东莞网络优化排名
免费企业网站建设要求_我们的服务理念和价值观_百度推广代理加盟_东莞网络优化排名

Java服务自动停止,Java服务内存溢出问题解决记录。

过程描述

服务器上的一个项目突然服务不了了,登录服务器一看,服务被停了,第一反应大概率就是内存溢出导致的,结果查看日志没有任何报错,就很奇怪,然后就在启动命令里面加上了一个命令,该命令的作用就是在发生内存溢出的时候会自动生成dump文件(jvm内存快照),把该文件下载到本地后用jvisualvm应用打开就能分析出问题。

# 当OutOfMemoryError发生时生成dump文件,-XX:HeapDumpPath指定生成后的文件存储路径
java -jar -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/home/test/dump/ -Xms6g -Xmx6g demo-0.0.1-SNAPSHOT.jar

过了一段时间服务又停了,日志依然没有报错,也没生成jvm内存快照文件,从这个情况来看应该是没有触发jvm内存溢出,否则已经生成内存快照文件,然后使用命令查看系统日志:

## 切换到系统日志目录 
cd /var/log
## 查看系统日志,grep 过滤一下,只查看Java相关的日志
sudo cat messages* |grep java

日志显示如下:

[zhh@official-website ~]$ cd /var/log
[zhh@official-website log]$ sudo cat messages* |grep java
Sep  3 01:49:38 official-website kernel: [27946]  1000 27946  2661073  1546426    3236        0             0 java
Sep  3 01:49:38 official-website kernel: Out of memory: Kill process 27946 (java) score 773 or sacrifice child
Sep  3 01:49:38 official-website kernel: Killed process 27946 (java) total-vm:10644292kB, anon-rss:6185704kB, file-rss:0kB, shmem-rss:0kB
Sep 21 01:49:48 official-website kernel: [ 2821]  1000  2821  2664978  1518600    3208        0             0 java
Sep 21 01:49:48 official-website kernel: Out of memory: Kill process 2821 (java) score 760 or sacrifice child
Sep 21 01:49:48 official-website kernel: Killed process 2821 (java) total-vm:10659912kB, anon-rss:6074400kB, file-rss:0kB, shmem-rss:0kB

从日志可以看出,由于Java服务占用的内存太多了,为了能保证系统的正常运行,操作系统就把Java服务kill停止了。为什么没有触发Java内存溢出的报错呢?因为设置的堆内存太大,实际使用的堆内存还没到达临界点。

这里说明一下什么情况下会触发jvm内存溢出的报错,一般两种情况:

1:实际使用内存达到设置的堆内存参数值(-Xmx)附近。

2:实际使用内存没有到达设置的堆内存参数值(-Xmx)附近,但是jvm向操作系统申请不到内存了,也就是说系统内存可能被其他服务占用或者设置的-Xmx参数过大。

继续排查,服务是部署到阿里云的服务器,所以是有内存监控的,于是就去看了内存监控,发现内存大小的占用随时间成梯度增长,涨上去就不会下来,说明内存没有被垃圾回收,那大概率就是代码写的有问题。

要找到是哪块代码有问题,最好的方法就是拿到jvm内存快照文件。通过查看内存监控后对比日志得到一个重要的信息,日志长得最猛的时间段就是系统一个视频会议功能使用的时间段,果然,在某次会议结束后进入阿里云内存监控界面一看,内存不出所料的飙升了。

然后就乘没人使用系统的时间段登录服务器,执行生成jvm内存快照的命令:

# 替换<pid>为Java进程的ID,file:输出文件名为heap.hprof,可自定义路径
jmap -dump:format=b,file=heap.hprof <pid>

注意:生成jvm内存快照的时候会影响系统的正常使用,最好是在系统闲置的时间段生成内存快照。而且如果系统内存快被占用满的时候是没法生成jvm内存快照的,因为生成内存快照也需要使用一点的内存。

jvm内存快照文件分析

拿到jvm内存快照后就使用jvisualvm打开,ps: 从jdk1.8以后包括最新几个版本的jdk1.8就已经不带jvisualvm了,如果需要jvisualvm只能自己到oracle官网去下载,新版的jvisualvm功能更齐全,不过目都是英文版。

导入内存快照文件后,界面显示一大堆对象和类,看得眼花缭乱,先不着急,先找找看看我们项目里面的类或者是对象,然后顺藤摸瓜即可,因为项目里面的对象都是互相引用的,jvisualvm会一一显示出来。

通过jvisualvm就能大概看出问题的所在了,界面显示有两个对象(FileInfo、Result)就是我们项目里面定义的,在内存中存在16万个FileInfo对象和12.7万个Result对象,通过界面的Reference引用栏和GC Root 垃圾回收根节点引用栏可以看到是被一个static变量cacheField引用,变量cacheField存在于类ReflectUtils中,好了,大概知道问题代码在哪了。

打开项目代码,看看什么情况:

结合上下文分析就可以知道,项目里面定义了一个static 变量 Map对象作为缓存存放部分对象,需要的时候从里面取,如果里面没有就放进去,只会往里面放,不会清除,最终导致Map里面存放的对象越来越多,除了重启服务,Map里面的对象是不会被清除的,因为是static修饰的类静态变量。

问题找到了就好办了,去掉缓存或者使用其他缓存方案。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com