一次Java内存泄漏的分析

测试服务器,跑了一夜之后,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个,而且数目不再增长,后台也没有再输出加载类的信息。

基本上问题解决。


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值