最近接到运营部门的反馈网站时常会出现小批量的502
且在网站出现502
以前反应特别慢,刷新几回之后又能够正常访问了。正则表达式
项目部署了两台机器,其中一台出现重启的状况,部分用户在访问当前服务器时正好机器重启了,致使访问异常。数组
查看生产环境日志发现其中一台机器重启了屡次,从warpper log
中能够发现warpper
在屡次ping
不通时自动重启了屡次,从运维那边确认这台服务器屡次出现无响应的状况。此时第一时间想到OOM
进一步查看日志并无发现OutOfMemoryException
抛出,也没有StackOverflowException
。bash
经过top
命令查看生产环境CPU
占用一直很是高,load
也一直高居不下,GC长时间占用CPU
资源。服务器
进一步查看GC
状况,发如今重启后很短的时间内FGC
次数达7W+;Old Generation
持续占用100%,而每次FGC
的时间又很是的短.运维
jstat -gcUtil [pid] 1000
jvm
在经过jmap -histo [pid]
查看内存实例状况也没有发现异常。工具
FGC
?。
因为没有触发OOM
手动添加如下启动参数,打印FGC
先后堆内存状况优化
-XX:+HeapDumpBeforeFullGC
-XX:+HeapDumpAfterFullGC
-XX:HeapDumpPath=/tmp
复制代码
果真,重启后短期内开始输出 dump网站
接下来使用jvisualvm
(JDK 自带的内存分析工具) 查看堆dump
文件。 如下列出FGC
先后的堆dump
类视图spa
对比FGC
先后发如今FGC
以前存在大量的int[]
和char[]
数组,且数组的length
都很是大,而这些大数组在FGC
以后又被有效的回收了。对jvm
垃圾回收有了解的同窗应该知道,jvm
为了不频繁的移动大对象会将大对象直接建立在Old Generation
。此时开始怀疑是否是Old Generation
的空间不够了,逐一排查线上环境的jvm
启动参数。
-Xms 2048
-Xmx 2048
...
-Xmn 2000
-
复制代码
......
最后发现,因为这台机器内存只有2G
而新生代分配的内存却达到了2000M
剩下的内存只有48M
。而大数组又会直接分配到Old Generation
当Old Generation
没有足够的空间来存放大数组对象时,就可能触发FGC
修改 -Xmn 683
默认新生代和老年代的比值为1:2
。从新发布问题解决,top
、jstat -gc
查看服务器状态各项数据都很是可爱。
因为项目已经跑了好几年,一开始的思路都在查找项目代码层面的问题,丝毫没有意Jvm
启动参数的问题,其实对一些有经验的同窗来讲发现问题搜集到的一些信息就能够定位问题。如:
GC
那张图就能够明显的看出问题。FGC
异常频繁(7W+),但FGCT
却不高(1.9W),这说明每次 FGC
的效率很是高。而每次FGC
的时候New Generation
的占用却很是少,能够排除是由于程序问题短期内产生大量新对象触发的 FGC
,这些都提供了直接的排查方向应该从:致使FGC
触发的条件入手,而不是找程序的问题。FGC
以前没有有效的触发YGC
。还有一点值得注意,jvm
启动参数的默认值在绝大多数状况下均可以完美的运行,不到系统优化的最后一步尽可能使用默认配置,最后还有一点疑问大量的int[]
、char[]
数组是从那里来得?经过分析项目中的代码,以及FGC
前存在大量的pattern
(正则表达式)相关对象分析,初步怀疑是由于项目中大量不规范的使用Pattern
致使的。
OutOfMemoryException
、StackOverflowException
抛出。GC
状况。GC
先后的dump
文件。