java FullGC问题解决示例

环境

JDK版本:1.7.0_45
操作系统:linux

问题背景

某系统(后面称:系统A)接入监控平台之后,收到java虚拟机持久代FullGC报警通知。对此我们对这个问题进行了分析,分析过程如下:

查看JVM持久代统计信息:

执行命令:ps -ef|grep java, jmap -permstat 8698

JVM持久代类信息如下(部分数据):
在这里插入图片描述

持久代统计信息分析:

我们发现JVM持久代中90%以上的全部是com/alibaba/fastjson/util/ASMClassLoader@0x00000007这个类型的信息,故猜ASMClassLoader这个类与JVM频繁FullGC有关,并找到了系统A中与之有关的代码:

public static String getJsonResult(ResultDO<?> result) {
		View view = new View();
		if (result.isSuccess()) {
			view.setData(result.getData());
			view.setResult(result_success);
		} else {
			view.setResult(result_error);
		}
		view.setCode(result.getCode());
		view.setMsg(result.getMsg());
		view.setCount(result.getCount());
		return FastJsonUtil.serializeFromObject(view);
}

在这段代码中,每次调用serializeFromObject方法都会new SerializeConfig ,而SerializeConfig 内部会new ASMSerializerFactory,ASMSerializerFactory内部又会new ASMClassLoader 。
ASMClassLoader 继承自ClassLoader,是一个类加载器,而类加载器有一个特性,就是即使对于同一个类,不同的类加载器加载之后也会被JVM视为不同的类。
所以,每调用一次FastJsonUtil.serializeFromObject(obj)方法都会创建一个新的类加载器去加载该对象的序列化类,每个新的类加载器都会创建一个新类,导致JVM持久代不断增长,最终导致FullGC。

推测结论:

系统A使用了公司内部一个sofa:0.0.2-SNAPSHOT版本包中的FastJsonUtil.serializeFromObject(view)这个方法,而这个方法则会导致JVM持久代不断增加最终导致FullGC。

测试验证:

使用公司内部sofa:0.0.2-SNAPSHOT版本包。
调用FastJsonUtil.serializeFromObject(view)这个方法之前,执行命令:
ps -ef | grep java ,jmap -permstat 8698
在这里插入图片描述

这里JVM持久代中com/alibaba/fastjson/util/ASMClassLoader@0x00000007这个类型的类对象就很少了,不会出现sofa:0.0.2-SNAPSHOT版本所出现的情况。

调用FastJsonUtil.serializeFromObject(view)这个方法10000次之后,执行命令:

ps -ef | grep java ,jmap -permstat 8698

JVM持久代类信息如下(部分数据):
在这里插入图片描述

最终结论:

sofa:0.0.2-SNAPSHOT版本包中的FastJsonUtil.serializeFromObject(view)这个方法容易导致JVM持久代FullGC问题。

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐