您的位置:首页 > 编程语言 > Java开发

一次Java内存泄漏的分析

2015-09-15 17:31 537 查看
测试服务器,跑了一夜之后,java.exe占用了大量内存(将近5GB),系统内存占用97%。

使用jconsole连接到该进程,发现一下的现象:

1. Heap内存占用比较正常,不到2个G。非Heap内存不正常,大概3个G。

2. 系统的线程数正常(500个左右)。

3. 可以断定问题处在非Heap内存。

进一步分析。查看Class页面。发现有一百多万个!!!类被加载。而且数目还在不断升高。与此同时非Heap内存也在不断升高。

就此大概定位为什么地方在不停的加载Class。在JConsole的Class页面,选中“详细输出“:



后,观察监控的Java进程的控制台。

发现控制台不停的输出:

[Loaded xxx.xxx.xxx from JAXB.......]

分析代码,Load的类是JAXB XML的映射类。该部分具体的逻辑就是,远程不停的向服务器报告数据。格式是XML。服务器收到XML后,调用JAXB将XML直接反序列化成对象。

观察具体的代码,发现每次调用JAXB的时候,都要调用newInstance方法:

public static Object unmarshall(String xml, Object obj)
{
try {
final StringReader xmlReader = new StringReader(xml);
final StreamSource xmlSource = new StreamSource(xmlReader);

JAXBContext context = JAXBContext.newInstance(obj.getClass());
Unmarshaller um = context.createUnmarshaller();

obj = um.unmarshal(xmlSource);
} catch (Exception e) {
logger.error("Error unmarshalling string " + xml, e);
}

return obj;
}


于是重构该方法,使用一个map保存context,不需要每次都调用newInstance:

private static Map<Class<?>, JAXBContext> contextStore = new ConcurrentHashMap<Class<?>, JAXBContext>();

protected static JAXBContext getContextInstance(Class<?> objectClass) throws JAXBException{
JAXBContext context = contextStore.get(objectClass);
if (context == null){
context = JAXBContext.newInstance(objectClass);
contextStore.putIfAbsent(objectClass, context);
}
return context;
}


然后进行测试,加载类的数目明显小了,只有不到10000个,而且数目不再增长,后台也没有再输出加载类的信息。

基本上问题解决。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: