• 填坑netty io.netty.util.internal.OutOfDirectMemoryError


    我们有个与外部交互的接口是采用netty http,具体版本netty-4.1.18,为什么使用这个版本,我也不知道,历史原因。

    由于netty都是异步请求,所以与外部交互总有些唯一的业务标识需要保存,以便前后数据可以勾兑。

    这里先说明下,netty里的ByteBuf在读取channelRead未进行写write操作时,需要自己释放release。这和本次Error关系不大,继续说重点。

    查看日志,首先发现了OutOfDirectMemoryError错误,这个错误也是间断性的出现,显然是内存不够用了,不管是heap还是direct。

    直接dump了一份堆内存日志,具体命令:jmap -dump:format=b,file=tomcat.dump pid。我们的服务是放在tomcat上的,jps一下,那个bootStrap就是。

    dump以后,找工具查看,推荐使用java自带的jvisualvm,在java目录的bin下,java自带的命令还是很好用的,比如上面提到的jps,jps -v比ps -ef |grep XXX 方便多了。

    装载dump文件后,如图所示:

    大概瞅一眼,某些类的实例也忒多了,满世界都是ConcurrentHashMap,绝壁有问题,这么造内存够用才怪,接着看到下面的netty有关的类实例,

    查看代码使用AttributeKey的地方,又看了源码实现,大概有些眉目,应该是对象创建过多,导致内存溢出了。

    每个实例下都挂这一个ConcurrentHashMap,不知道是不是我们的用法有问题,先不管了,先解决问题,

    发现代码每次请求都创建一个连接channel,每次都会全局保存一个AttributeKey,以便在请求异步响应时,勾兑原始数据,so,每天几百万请求就有点春困秋乏了,

    借用AttributeKey的思路,改为自己全局保存一个ConcurrentHashMap,然后键值对保存唯一业务标识,并且在异步处理之后remove过时数据。

    AttributeKey我翻了翻源码,真没看到在哪里可以释放的地方,有一个set(null)当然代码并没有使用过后设空操作,但是AttributeKey内部的haspMap不会自动释放。

    修改以后,重新部署。观察了几天,dump了新的内存日志,并没有发现过多的对象实例。继续观察一段时间。

    有关内存溢出的问题其实并没有想的那么困难,内存不够用自然会FullGC或者内存溢出,有些内存泄漏也会最终引发FullGC或内存溢出,找到过多的垃圾对象,

    该释放的释放,该单例的使用单例,能重用的尽量重用,应该没什么问题,看看dump文件基本就找到问题根源了。

  • 相关阅读:
    实验四: Android程序设计
    实验三 敏捷开发与XP实践-1
    mini dc课堂练习补交
    20155216 2016-2017-2 《Java程序设计》第十周学习总结
    第十二周课上练习
    20155210 潘滢昊 Java第三次实验
    20155210 2016-2017-2 《Java程序设计》第10周学习总结
    20155210 潘滢昊2016-2017-2 《Java程序设计》第9周学习总结
    20155210潘滢昊 Java第二次试验
    20155210潘滢昊 2016-2017-2 《Java程序设计》第8周学习总结
  • 原文地址:https://www.cnblogs.com/render-inside/p/9015891.html
Copyright © 2020-2023  润新知