我试图从文件中读取大量数据(10k-20k记录)(10个线程运行10分钟)。我得到一个例外:
Exception in thread "main" Exception in thread "Thread-26" java.lang.OutOfMemoryError: Java heap space
at java.util.Arrays.copyOfRange(Unknown Source)
at java.lang.String.<init>(Unknown Source)
at java.io.BufferedReader.readLine(Unknown Source)
at java.io.BufferedReader.readLine(Unknown Source)
我收到以下代码段的上述错误消息。 我一直试图调试这个:我最接近的是使用CharSequence。但我仍然得到堆异常。 (此时 - 任何人都可以帮助我理解为什么CharSequence会更好吗?=&gt;它似乎会在主内存中加载少量数据,但最终所有数据都需要在主内存中。)
如果持续1分钟,我可以运行代码。但是接近10分钟的任何事情都会爆炸。有没有一种有效的方法来读取文件?
**此代码是研究的一部分,我仍在重新考虑它,因此确实存在许多效率低下的代码。
try{
for(int i=0; i<threadCount; i++){
fstream = new FileInputStream(dir+"//read"+machineid+"-"+i + ".txt");
// Use DataInputStream to read binary NOT text.
BufferedReader br = new BufferedReader(new InputStreamReader(fstream));
String line;
// Read File Line By Line
String[] tokens;
while ((line = br.readLine()) != null) {
tokens = line.split(",");
logObject record = new logObject(tokens[0], tokens[1], tokens[2],tokens[3], tokens[4], tokens[5], tokens[6], tokens[7], "", tokens[8]);
toBeProcessed[toBeProcessedArraySz] = record;
toBeProcessedArraySz++;
if(readToValidate == toBeProcessedArraySz){
try {
semaphore.acquire();
} catch (InterruptedException e) {
e.printStackTrace(System.out);
}
//create thread to process the read records
ValidationThread newVThread = new ValidationThread(props,toBeProcessed, updateStats, initCnt, semaphore, finalResults, staleSeqSemaphore, staleSeqTracker, seqTracker, seenSeqSemaphore, toBeProcessedArraySz, freshnessBuckets,bucketDuration);
vThreads.add(newVThread);
toBeProcessedArraySz = 0;
toBeProcessed = new logObject[readToValidate];
semaphore.release();
newVThread.start();
}
}
br.close();//remove to test
fstream.close();
}
}catch(Exception e){
e.printStackTrace(System.out);
}
答案 0 :(得分:2)
尝试使用更大的堆空间启动JVM;即致电java -Xmx=1G yourProgram
。仅通过代码片段很难说出为什么程序内存不足。您还可以使用诸如Eclipse MAT之类的分析器工具来准确查看哪些对象导致内存已满。
答案 1 :(得分:2)
如果您不理解问题,请不要简单地增加堆大小。增加堆大小并不能解决您的问题。它只是将它推迟到更糟糕的时间(需要更长时间才能发生)。
问题是当堆已满时,程序不会等待读取数据。这是一个简单的问题。您的算法中没有任何内容可以阻止读取线程进一步填充堆。如果处理线程无法跟上读取速度,则必须在某个时刻发生OOME。你必须改变这个:对于数据读取线程,如果最大数量的处理线程处于活动状态,则添加一些暂停读取的方法,并在处理线程数再次低于此阈值时继续读取数据。
此外:
也许您的某个文件已损坏,并且包含很长的行,例如&GT;一条线500MB。找出OOME是否总是出现在同一行(这很可能是这种情况),然后检查该行。它最后有哪个行分隔符\n
或\r\n
?或\r
?