【发布时间】:2019-02-01 19:29:30
【问题描述】:
在这段代码的 sn-p 中,我使用 Apache POI 库加载了一个大小为 10MB 的 excel 文件。这消耗了将近 2GB 的内存。 在遍历了所有行之后,我终于调用了 close 方法。但是,似乎 GC 并没有释放此流和对象消耗的空间。并且仍然使用 2GB + 400MB 内存。
有什么想法吗?
这是我的代码:
public List<Meter> loadFile(File excelFile) throws IOException, InvalidFormatException {
List<Meter> allMeters = new ArrayList<>();
InputStream inputStream = new FileInputStream(excelFile);
XSSFWorkbook workbook = new XSSFWorkbook(inputStream);
Sheet sheet1 = workbook.getSheetAt(0);
Iterator<Row> rows_sheet1 = sheet1.iterator();
if (rows_sheet1.hasNext()) {
rows_sheet1.next(); //skip header
}
while (rows_sheet1.hasNext()) {
try {
Row currentRow = rows_sheet1.next();
Cell meterNoCell = currentRow.getCell(0);
Cell startPeriodCell = currentRow.getCell(1);
Cell endPeriodCell = currentRow.getCell(2);
Cell previousConsumption = currentRow.getCell(3);
Cell currentConsumption = currentRow.getCell(4);
Cell periodConsumptionCell = currentRow.getCell(5);
meterNoCell.setCellType(CellType.STRING);
startPeriodCell.setCellType(CellType.STRING);
endPeriodCell.setCellType(CellType.STRING);
//Reading values from above_defined cells and filling allMeters list (defined at the begining of the function).
//......
//Done
}
catch (Exception ex) {
Logger.getLogger(MetersList.class.getName()).log(Level.SEVERE, null, ex);
}
}
workbook.close();
inputStream.close();
return allMeters;
}
【问题讨论】:
-
你如何衡量内存使用情况?
-
进行内存转储并分析它以了解您的内存中剩余的对象类型
-
请注意,每次
close()操作后GC不会自动调用,它是由JVM调用的,调用取决于它的GC设置。您可以使用jvisualvm来监控您的Java 进程,在那里您可以找到“Perform GC”按钮。请尝试一下,您会发现 GC 后堆使用量减少了。 -
@Arman 任务管理器不会为您提供有关 GC 活动的信息 - JVM 将在操作系统内存中保留一些空间并根据需要进行增长。但是 java 进程使用的内存包括已使用和未使用的堆空间(即它不会在 GC 后减少)。您需要以不同的方式监控 GC,例如使用 jvisualvm 或飞行记录器。
-
解引用inputStream和workbook可以更早触发GC,试一试。
标签: java memory garbage-collection out-of-memory inputstream