请选择 进入手机版 | 继续访问电脑版

默认
发表评论 8
[已回复] 求教MobileIMSDK里OutOfDirectMemoryError, 出现原因?
网上说是netty的堆外内存垃圾回收机制跟jvm不一样的原因。解决方案还没有看到怎么解。





[2018-11-05 16:12:19,792][WARN, Slf4JLogger.java:151] An exceptionCaught() event was fired, and it reached at the tail of the pipeline. It usually means the last handler in the pipeline did not handle the exception.
io.netty.util.internal.OutOfDirectMemoryError: failed to allocate 16777216 byte(s) of direct memory (used: 503316480, max: 510066688)
        at io.netty.util.internal.PlatformDependent.incrementMemoryCounter(PlatformDependent.java:640)
        at io.netty.util.internal.PlatformDependent.allocateDirectNoCleaner(PlatformDependent.java:594)
        at io.netty.buffer.PoolArena$DirectArena.allocateDirect(PoolArena.java:764)
        at io.netty.buffer.PoolArena$DirectArena.newChunk(PoolArena.java:740)
        at io.netty.buffer.PoolArena.allocateNormal(PoolArena.java:244)
        at io.netty.buffer.PoolArena.allocate(PoolArena.java:214)
        at io.netty.buffer.PoolArena.allocate(PoolArena.java:146)
        at io.netty.buffer.PooledByteBufAllocator.newDirectBuffer(PooledByteBufAllocator.java:324)
        at io.netty.buffer.AbstractByteBufAllocator.directBuffer(AbstractByteBufAllocator.java:185)
        at io.netty.buffer.AbstractByteBufAllocator.directBuffer(AbstractByteBufAllocator.java:176)
        at io.netty.buffer.AbstractByteBufAllocator.ioBuffer(AbstractByteBufAllocator.java:137)
        at io.netty.channel.DefaultMaxMessagesRecvByteBufAllocator$MaxMessageHandle.allocate(DefaultMaxMessagesRecvByteBufAllocator.java:80)
        at net.nettime.mobileimsdk.server.netty.MBUDPServerChannel.doReadMessages(MBUDPServerChannel.java:148)
        at io.netty.channel.nio.AbstractNioMessageChannel$NioMessageUnsafe.read(AbstractNioMessageChannel.java:75)
        at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:645)
        at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:580)
        at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:497)
        at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:459)
        at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:858)
        at io.netty.util.concurrent.DefaultThreadFactory$DefaultRunnableDecorator.run(DefaultThreadFactory.java:138)
        at java.lang.Thread.run(Thread.java:745)


即时通讯网 - 即时通讯开发者社区! 来源: - 即时通讯开发者社区!

标签:MobileIMSDK
上一篇:[已回复] 求助MobileIMSDK的android版切换语言时APP闪退了?下一篇:[已回复] 求教MobileIMSDK的udp压力测试该用什么包来测?
推荐方案
评论 8
你这是怎么弄出来的?这是在做什么样的功能?

你参考一下这个帖子:https://bbs.csdn.net/topics/392175630,用JVM调试工具,看看代码运行时的JVM内部的情况,具体你可以安装一个JProfile,用它来观察JVM微观情况,就很容易知道发生问题的原因。

如果你对JVM的基本知识和JProfile的使用不怎么了解,建议系统地学习一下,这种深水区的问题,如果用初学者的心态来看,是解决不了的。
签名: “程序员半夜下班取快件,被快递员误认为"小偷"”,又是抹黑程序员。。
引用:JackJiang 发表于 2018-11-05 16:59
你这是怎么弄出来的?这是在做什么样的功能?

你参考一下这个帖子:https://bbs.csdn.net/topics/392175 ...

聊天系统,上线有2个月了吧,每天在线300个左右。服务端已经出现两次这个内存溢出问题。先考虑以下方案操作,发现启动参数存在DisableExplicitGC :
1)-XX:MaxDirectMemorySize 加大,该参数默认是 64M ,可以根据需求调大试试;
2)检查 JVM 参数里面有无: -XX:+DisableExplicitGC ,如果有就去掉.
引用:eugen_wu 发表于 2018-11-05 17:13
聊天系统,上线有2个月了吧,每天在线300个左右。服务端已经出现两次这个内存溢出问题。先考虑以下方案操 ...

你看你这个溢出针对的是netty,你是自已将RainbowChat里默认用的MINA稳定版库替换成netty版的?有没有改什么代码?netty用的是哪个版?

RainbowChat默认用的MINA库是绝对不会出现这个问题。我建议你找个对等的运行条件,长测一下作一个参照,尝试找出问题。
另外,我在上面的回贴里,让你研究JVM和JProfile,应该很容易能找出问题,JProfile可以准确地检测到哪些对象、哪个方法产生的内存问题。
签名: “程序员半夜下班取快件,被快递员误认为"小偷"”,又是抹黑程序员。。
引用:JackJiang 发表于 2018-11-05 19:35
你看你这个溢出针对的是netty,你是自已将RainbowChat里默认用的MINA稳定版库替换成netty版的?有没有改 ...

server/MobileIMSDKServerDemoX_netty_deploy_v3.1b20171211    代码改了一点。  目前还不知道哪里出问题,需要研究下
引用:eugen_wu 发表于 2018-11-08 17:24
server/MobileIMSDKServerDemoX_netty_deploy_v3.1b20171211    代码改了一点。  目前还不知道哪里出问题 ...

你可以把你改过的部分贴出来,并说说你的修改思路,一起看看
签名: “程序员半夜下班取快件,被快递员误认为"小偷"”,又是抹黑程序员。。
引用:JackJiang 发表于 2018-11-08 19:33
你可以把你改过的部分贴出来,并说说你的修改思路,一起看看

我开放了一个消息发送前的处理接口,服务端收到消息后,可以自定义处理下消息体,比如加服务端时间戳,敏感词校验什么的。其他地方没改。
修改代码:1、
package net.openmob.mobileimsdk.server.event;

        import net.openmob.mobileimsdk.server.protocal.Protocal;

public interface MessageBeforeSendHandler {

    public Protocal onC2CMessageReceiveBeforeSend(final Protocal pFromClient);

}

2、GlobalSendHelper的 sendDataC2C,增加
                        //消息处理开放接口
                        Protocal pFromClient2 = pFromClient;
                        if (null != messageHandler) {
                                pFromClient2 = messageHandler.onC2CMessageReceiveBeforeSend(pFromClient);
                        }
源码有个疑问请教下,MBUDPServerChannel 的 doReadMessages 方法。return 0 的情况,freeBuffer可能有两个值。buffer.release();在false情况下不调用?



@Override
protected int doReadMessages(List<Object> list) throws Exception
{
   DatagramChannel javaChannel = javaChannel();
   RecvByteBufAllocator.Handle allocatorHandle = unsafe().recvBufAllocHandle();
   ByteBuf buffer = allocatorHandle.allocate(config.getAllocator());
   allocatorHandle.attemptedBytesRead(buffer.writableBytes());
   
   boolean freeBuffer = true;
   try
   {
      // read message
      ByteBuffer nioBuffer = buffer.internalNioBuffer(buffer.writerIndex(), buffer.writableBytes());
      int nioPos = nioBuffer.position();
      
      InetSocketAddress inetSocketAddress = (InetSocketAddress) javaChannel.receive(nioBuffer);
      if (inetSocketAddress == null)
         return 0;
      
      allocatorHandle.lastBytesRead(nioBuffer.position() - nioPos);
      buffer.writerIndex(buffer.writerIndex() + allocatorHandle.lastBytesRead());
      
      // allocate new channel or use existing one and push message to it
      MBUDPChannel udpchannel = channels.get(inetSocketAddress);
      if ((udpchannel == null) || !udpchannel.isOpen())
      {
         udpchannel = new MBUDPChannel(this, inetSocketAddress);
         channels.put(inetSocketAddress, udpchannel);
         list.add(udpchannel);
         
         udpchannel.addBuffer(buffer);
         freeBuffer = false;
         
         return 1;
      }
      else
      {
         udpchannel.addBuffer(buffer);
         freeBuffer = false;
         
         if (udpchannel.isRegistered())
            udpchannel.read();
         
         return 0;
      }
   }
   catch (Throwable t)
   {
      PlatformDependent.throwException(t);
      return -1;
   }
   finally
   {
      if (freeBuffer)
         buffer.release();
   }
}

引用:eugen_wu 发表于 2018-11-09 10:36
源码有个疑问请教下,MBUDPServerChannel 的 doReadMessages 方法。return 0 的情况,freeBuffer可能有两个 ...

应该不至于,这个我没注意,你调试一下试试,有进展了随时上来反馈讨论。

你记得一定要把jprofile这个工具用熟,它对你大有好处。
签名: “程序员半夜下班取快件,被快递员误认为"小偷"”,又是抹黑程序员。。
打赏楼主 ×
使用微信打赏! 使用支付宝打赏!

返回顶部