你好,目前我正在为Moco框架(https://github.com/dreamhead/moco)开发一个Arquillian扩展。 Moco用于测试RESTful服务,并依赖Netty处理通信。目前Moco正在使用Netty 4.0.18.Final。
但是我在容器内运行Moco(和Netty服务器)时发现了一个问题(Arquillian在容器内运行测试)并且它正确启动但是当取消部署应用程序并且服务器关闭时,下一个日志错误消息被打印:
严重:Web应用程序[/ ba32e781-3a18-44b3-9547-7c26787f3fe7]似乎已经启动了一个名为[pool-2-thread-1]的线程,但未能将其停止。这很可能造成内存泄漏。 abr 08,2014 10:29:06 AM org.apache.catalina.loader.WebappClassLoader checkThreadLocalMapForLeaks 严重:Web应用程序[/ ba32e781-3a18-44b3-9547-7c26787f3fe7]使用[io.netty.util.internal.ThreadLocalRandom $ 2]类型的键创建了一个ThreadLocal(值[io.netty.util.internal.ThreadLocalRandom $ 2 @ 77468cae])和类型[io.netty.util.internal.ThreadLocalRandom]的值(值[io.netty.util.internal.ThreadLocalRandom@6cd3851])但在Web应用程序停止时无法将其删除。线程将随着时间的推移而更新,以避免可能的内存泄漏。
基本上似乎有些线程在服务器尝试关闭时尚未关闭。
从应用程序部署到服务器的Arquillian扩展的角度来看,调用Moco的start方法,在取消部署应用程序之前,调用Moco的stop方法。
但是,让我告诉你Moco的代码:
public int start(final int port, ChannelHandler pipelineFactory) {
ServerBootstrap bootstrap = new ServerBootstrap();
bootstrap.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.childHandler(pipelineFactory);
try {
future = bootstrap.bind(port).sync();
SocketAddress socketAddress = future.channel().localAddress();
address = (InetSocketAddress) socketAddress;
return address.getPort();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
并且stop方法如下:
private void doStop() {
if (future != null) {
future.channel().close().syncUninterruptibly();
future = null;
}
所以似乎close方法在杀死所有线程之前返回,因此容器会警告你可能存在内存泄漏。
因为我从未使用过Netty,所以我想知道是否有办法确保整个Netty运行时都关闭。
非常感谢你的帮助。
答案 0 :(得分:0)
我也是Netty的新手(并且不熟悉Arquillian),但基于Netty Docs示例,我相信您可能不会关闭您创建的EventLoopGroup
(bossGroup,workerGroup)。来自Netty 4.0 User Guide:
关闭Netty应用程序通常就像关闭通过shutdownGracefully()创建的所有EventLoopGroup一样简单。它返回一个Future,当EventLoopGroup完全终止并且所有属于该组的频道都已关闭时,它会通知您。
所以你的doStop()方法可能如下所示:
private void doStop() {
workerGroup.shutdownGracefully();
bossGroup.shutdownGracefully();
}
Netty文档中的一个示例:Http Static File Server Example