gpt4 book ai didi

java - NioSocketChannel$WriteRequestQueue 导致 OutOfMemory

转载 作者:搜寻专家 更新时间:2023-11-01 03:26:46 26 4
gpt4 key购买 nike

我正在使用 Netty 执行大型文件上传。它工作正常,但客户端使用的 RAM 似乎随着文件的大小而增加。这不是预期的行为,因为一切都从读取源文件通过管道传输到写入目标文件。

起初,我想到了一种自适应缓冲区,直到达到 Xmx,但是 将 Xmx 设置为合理的值 (50M) 会导致在开始上传后不久出现 OutOfMemoryError。在使用 Eclipse Memory Analyzer 进行一些研究之后,保留堆内存的对象似乎是:

org.jboss.netty.channel.socket.nio.NioSocketChannel$WriteRequestQueue

是否有任何选项可以为此队列设置限制,或者我是否必须使用 ChannelFutures 编写自己的队列以控制字节数并在达到限制时阻塞管道?

谢谢你的帮助,

问候,

雷诺

最佳答案

Netty Github 上@normanmaurer 的回答

你应该使用

Channel.isWritable()

检查“队列”是否已满。如果是这样,您将需要检查是否有足够的空间来写入更多内容。因此,如果您快速写入数据以将其发送给客户端,就会发生您看到的效果。当尝试通过 DefaultFileRegion 或 ChunkedFile 写入文件时,您可以解决此类问题。


@normanmaurer 谢谢,我错过了 Channel 的这个方法!我想我需要看看里面发生了什么:

org.jboss.netty.handler.stream.ChunkedWriteHandler

更新时间:2012/08/30这是我为解决问题而编写的代码:

public class LimitedChannelSpeaker{
Channel channel;
final Object lock = new Object();
long maxMemorySizeB;
long size = 0;
Map<ChannelBufferRef, Integer> buffer2readablebytes = new HashMap<ChannelBufferRef, Integer>();

public LimitedChannelSpeaker(Channel channel, long maxMemorySizeB) {
this.channel= channel;
this.maxMemorySizeB = maxMemorySizeB;
}

public ChannelFuture speak(ChannelBuffer buff) {
if (buff.readableBytes() > maxMemorySizeB) {
throw new IndexOutOfBoundsException("The buffer is larger than the maximum allowed size of " + maxMemorySizeB + "B.");
}
synchronized (lock) {
while (size + buff.readableBytes() > maxMemorySizeB) {
try {
lock.wait();
} catch (InterruptedException ex) {
throw new RuntimeException(ex);
}
}
ChannelBufferRef ref = new ChannelBufferRef(buff);
ref.register();
ChannelFuture future = channel.write(buff);
future.addListener(new ChannelBufferRef(buff));
return future;
}
}

private void spoken(ChannelBufferRef ref) {
synchronized (lock) {
ref.unregister();
lock.notifyAll();
}
}

private class ChannelBufferRef implements ChannelFutureListener {

int readableBytes;

public ChannelBufferRef(ChannelBuffer buff) {
readableBytes = buff.readableBytes();
}

public void unregister() {
buffer2readablebytes.remove(this);
size -= readableBytes;
}

public void register() {
buffer2readablebytes.put(this, readableBytes);
size += readableBytes;
}

@Override
public void operationComplete(ChannelFuture future) throws Exception {
spoken(this);
}
}
}

关于java - NioSocketChannel$WriteRequestQueue 导致 OutOfMemory,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12173963/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com