我正在套接字服务器上的 while 循环中接收记录。其中每个记录都有一个消息类型,后跟消息长度和实际消息内容。
问题是,因为我得到了大约一百万条记录,并且每条记录的记录大小为 277 字节。因此,在大约 40000 条记录之后,我收到 OutOfMemory 错误。代码流程如下所示:
while (true) {
msgType = dIn.readByte();
int msgIntType = msgType & 0xff;
// get message length
int msgIntLen = dIn.readInt();
if (msgIntLen != 0) {
msgContent = new byte[msgIntLen];
switch(msgIntType) {
case 4:
//case MSG_DATA:
// MSG_DATA
recordCount++;
processData(msgContent);
if (recordCount == 2000) {
sendACK(dOut, msgIntType);
logger.info("sent ACK for MSG_DATA");
recordCount = 0;
}
break;
}
我通过在每处理 2000 条记录后发送 ACK 后显式调用 System.gc() 解决了 OutOfMemory 问题,现在它工作得很好,能够在 10 分钟内处理 100 万条记录,没有任何错误。用于调用 System.gc() 的 case 语句的修改代码如下所示:
case 4:
//case MSG_DATA:
// MSG_DATA
recordCount++;
processData(msgContent);
if (recordCount == 2000) {
sendACK(dOut, msgIntType);
logger.info("sent ACK for MSG_DATA");
recordCount = 0;
System.gc();
}
break;
但是我在其他一些帖子上读到调用 System.gc() 不是一个好的设计方法?是这样吗 ?如果是的话,你们能给我建议一些其他方法来消除这个 OutOfMemory 错误吗?
提前致谢 -JJ
编辑:processData() 的逻辑:
public void processData(byte[] msgContent) throws Exception {
InputStreamReader inp = new InputStreamReader(
new ByteArrayInputStream(msgContent));
BufferedReader br = null;
try {
br = new BufferedReader(inp);
String line;
while ((line = br.readLine()) != null) {
process each line
.
}
} catch (Exception e) {
logger.error("exception in " + Utils.getExecutingMethodName(e)
+ " :" + e.getMessage());
} finally {
try {
if (br != null)
br.close();
} catch (IOException e) {
logger.error("Error: " + e);
}
}
}
最佳答案
您是否未能关闭某些资源并依赖终结器线程来获取它们?或者您是否刚刚添加了一个终结器(可能不必要),该终结器会阻止立即释放大量内存。
关于java - 删除分配给字节数组的内存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5807465/