工作记录:java.lang.OutOfMemoryError: PermGen space问题排查处理
作者:互联网
项目上线当天,预计实时用户在线人数 500-1000 人左右,系统网络请求 QPS 预计达到 5000 以上。Linux 服务器性能 16 核 32 G,系统间隔半小时崩溃一次,查看生产环境日志排查系统崩溃原因并修复。
日志分割
将 tomcat 目录下的 conf 目录下 logging.properties 文件 设置 debug 模式。
打印所有请求输出日志时,请求量过大,日志不断在增长造成文件过大,无法精确快速定位问题日志。
通过设置日志按天分割,解决日志过大问题
设置完成后将当天的服务器日志down到本地,编辑器打开日志并定位到异常信息,异常如下报错信息:
java.lang.OutOfMemoryError: PermGen space
原因分析:
永久代是 HotSot 虚拟机对方法区的具体实现,存放了被虚拟机加载的类信息、常量、静态变量、JIT编译后的代码等。
JDK8 后,元空间替换了永久代,元空间使用的是本地内存,还有其它细节变化:
字符串常量由永久代转移到堆中和永久代相关的 JVM 参数已移除
可能原因有如下几种:
1、在Java7之前,频繁的错误使用String.intern()方法
2、运行期间生成了大量的代理类,导致方法区被撑爆,无法卸载
3、应用长时间运行,没有重启。没有重启 JVM 进程一般发生在调试时
解决方法:
因为该OOM原因比较简单,解决方法有如下几种:
1、检查是否永久代空间或者元空间设置的过小
2、检查代码中是否存在大量的反射操作
3、dump之后通过mat检查是否存在大量由于反射生成的代理类
4、放大招,重启JVM
生产环境的内存情况
使用 jps 命令查看配置了JVM的服务,端口号
jps
查看某个进程(端口号)JVM 的 GC 使用情况
jstat -gc 端口号 刷新时间
jstat -gc 71614 5000
GC 使用情况字符说明
S0C:年轻代中第一个survivor(幸存区)的容量 (字节)
S1C:年轻代中第二个survivor(幸存区)的容量 (字节)
S0U:年轻代中第一个survivor(幸存区)目前已使用空间 (字节)
S1U:年轻代中第二个survivor(幸存区)目前已使用空间 (字节)
EC:年轻代中Eden(伊甸园)的容量 (字节)
EU:年轻代中Eden(伊甸园)目前已使用空间 (字节)
OC:Old代的容量 (字节)
OU:Old代目前已使用空间 (字节)
MC:方法区容量 (字节)
MU:方法区已使用空间 (字节)
YGC:从应用程序启动到采样时年轻代中gc次数
YGCT:从应用程序启动到采样时年轻代中gc所用时间(s)
FGC:从应用程序启动到采样时old代(全gc)gc次数
FGCT:从应用程序启动到采样时old代(全gc)gc所用时间(s)
GCT:从应用程序启动到采样时gc用的总时间(s)
发现永久代内存使用百分比偏高 MU/MC(83%)
修改元空间的内存大小,将大小设置成原设置的两倍
修改jvm参数
1.查看 catalina.sh文件,未发现设置的参数信息。添加如下配置
JAVA_OPTS="-Xms16005m -Xmx16005m -Xss1024K -XX:MetaspaceSize=200m -XX:MaxMetaspaceSize=512m"
正常增加如上配置即可重启后打开日志查看启动参数,发现未生效
排查是否有覆盖参数的情况,查看bin目录下是否有setenv.sh文件,如果存在则查看内容配置,setenv.sh文件配置如下:
JAVA_OPTS="-Xms16005m -Xmx16005m -Xss512K -XX:MetaspaceSize=200m -XX:MaxMetaspaceSize=256m"
修改成
JAVA_OPTS="-Xms16005m -Xmx16005m -Xss1024K -XX:MetaspaceSize=200m -XX:MaxMetaspaceSize=512m"
重启服务后参数生效,系统崩溃问题解决。
标签:lang,PermGen,java,字节,代中,XX,gc,JVM,日志 来源: https://www.cnblogs.com/sanxingblogs/p/14272346.html