简体   繁体   中英

Netty causing memory leak in tomcat

I'm using Netty 4.0.26.Final along with Tomcat 8 to implement an embedded TCP server inside a web application.

The problem is that when I stop Tomcat I'm getting this message :

The web application [app] appears to have started a thread named 

[nioEventLoopGroup-2-1] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread:

sun.nio.ch.WindowsSelectorImpl$SubSelector.poll0(Native Method)
 sun.nio.ch.WindowsSelectorImpl$SubSelector.poll(WindowsSelectorImpl.java:296)
 sun.nio.ch.WindowsSelectorImpl$SubSelector.access$400(WindowsSelectorImpl.java:278)
 sun.nio.ch.WindowsSelectorImpl.doSelect(WindowsSelectorImpl.java:159)
 sun.nio.ch.SelectorImpl.lockAndDoSelect(SelectorImpl.java:87)
 sun.nio.ch.SelectorImpl.select(SelectorImpl.java:98)
 io.netty.channel.nio.NioEventLoop.select(NioEventLoop.java:622)
 io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:310)
 io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:111)
 io.netty.util.concurrent.DefaultThreadFactory$DefaultRunnableDecorator.run(DefaultThreadFactory.java:137)

I've tried using this class to shutdown the threads before closing tomcat but I'm still having the same problem.

@Component
public class MyAppServletContextListener implements ServletContextListener{

    @Override
    public void contextInitialized(ServletContextEvent arg0) {
    }


    @Override
    public void contextDestroyed(ServletContextEvent arg0) {
        TrackingDaemon trackingDaemon= (TrackingDaemon) ApplicationContextProvider.getBean("trackingDaemon");
        trackingDaemon.bossGroup.shutdownGracefully();
        trackingDaemon.workerGroup.shutdownGracefully();
    }


}

BossGroup and workerGroup are:

EventLoopGroup bossGroup = new NioEventLoopGroup(); 
EventLoopGroup workerGroup = new NioEventLoopGroup();

Any help will be appreciated..

I have had this problem with netty 4 and tomcat 7 and solved it by capturing the future event from shutdownGracefully() and awaiting its completion. The method below is called when closing down the application.

private void stopChannel() {
 log.trace("Stopping server socket on port '{}'", port);
 sendMessageService.deregisterMessageSender(endpointId);
 try {
   for (Channel channel : channels) {
     if (channel != null) {
       channel.close();
     }
   }
   serverChannel.close().sync();
   log.trace("Server socket on port '{}' stopped.", port);
 } catch (InterruptedException e) {
    throw new RuntimeException(e);
 } finally {
    Future<?> fc = connectionGroup.shutdownGracefully();
    Future<?> fw = workerGroup.shutdownGracefully();
   try {
     fc.await(); // when shutting down in tomcat waits for the netty threads to die
     fw.await();
   } catch (InterruptedException e) {
    throw new RuntimeException(e);
  }
   log.trace("Server workerGroup has shutdown successfully on port '{}'", port);
}

}

I guess you will need to do:

    trackingDaemon.bossGroup.shutdownGracefully().syncUninterruptibly();
    trackingDaemon.workerGroup.shutdownGracefully().syncUninterruptibly();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM