I am receiving records in while loop at a socket server. where each records has a msg type followed by message length and actual message content.
The problem is that since I get around a million records and each record has a record size of 277 bytes. So, after around 40000 records, I get OutOfMemory error. The code flow looks something like this:
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;
}
I resolved the OutOfMemory issue by explicitly calling System.gc() after sending ACK after every 2000 records processed and now it works perfectly fine and able to handle 1 million records without any error in less than 10 minutes. The modified code for case statement for calling System.gc() looks like:
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;
But I read here on some other posts that calling System.gc() is not a good design approach ? Is it so ? If yes, could you guys suggest me some other way to get rid of this OutOfMemory error ?
Thanks in advance -JJ
EDIT: logic for 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);
}
}
}
processData()do? Is it possible it keeps a reference to the byte array somehow?-XX:+HeapDumpOnOutOfMemoryErrorand load the dump produced in a tool like YourKit. I think VisualVM can load it too.finallyblock there (or even thecloseas there is no actual resource involved. (I think it was possibly a mistake to putcloseonInputStreamandReader.)