我正在开发用于文件交换的客户端-服务器架构,这是为了我自己的目的。除了内存使用之外,一切都很好。发送一些文件后,我意识到当我尝试发送一些视频(大约 900MB)时,我的应用程序内存管理不是那么有效,我的客户端和服务器的内存使用量约为 1,5GB。
我使用了 NetBeans 的 Profiler,它说问题是字节数组。
//Client side
FileInputStream f = new FileInputStream(file);
FileChannel ch = f.getChannel();
ByteBuffer bb = ByteBuffer.allocate(8192*32);
int nRead = 0;
while ((nRead = ch.read(bb)) != -1) {
if (nRead == 0) {
continue;
}
bb.position(0);
bb.limit(nRead);
send.writeObject(Arrays.copyOfRange(bb.array(), 0, nRead));
send.flush();
bb.clear();
}
f.close();
ch.close();
bb.clear();
send.writeObject(0xBB);
send.flush();
//Server side
FileOutputStream fos = new FileOutputStream(file);
FileChannel fco = fos.getChannel();
ByteBuffer buffer = ByteBuffer.allocate(8192 * 32);
do {
Object received = download.readObject();
if (received instanceof byte[]) {
byte[] bytes = (byte[]) received;
buffer.put(bytes);
buffer.flip();
buffer.position(0);
buffer.limit(bytes.length);
fco.write(buffer);
buffer.clear();
} else if (received instanceof Integer) {
Integer tempx = (Integer) received;
state = (byte) (tempx & (0xFF));
}
} while (received != (byte) 0xBB);
fco.close();
fos.close();
有没有办法修复它,我的意思是可以清理使用过的内存吗?限制字节缓冲区无法正常工作,因此我限制了缓冲区中的字节数组,我没有附加整个代码,因为处理文件是问题所在。
来自探查器的屏幕 - 客户端的内存使用情况 /image/ouTDk.png
最佳答案
- 您的缓冲区是 8192 乘以 32。如果您有内存问题,请减小它们。出于网络目的,您不需要那么大。 256k 的写法也很奇怪。
- 不要创建毫无意义的字节数组副本。 ObjectOutputStream.writeUnshared() 将执行您需要的操作。
- 我强烈建议摆脱序列化并仅复制字节。代码变得更加简单,数据副本也更少,尤其是在接收端。
关于java - 在将 Sockets 与 NIO 结合使用时防止内存使用率过高,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20713016/