题目:什么是 POI,为什么它会导致内存溢出?
难度:low
标签:practice/java, jvm/memory
评分:⭐⭐⭐☆☆(3/5)
POI 是用来进行 excel 等表格解析的工具,内存中要加载 excel 等表格的内容,如果使用全量加载,单次加载过大的 excel 表格,就有可能导致内存溢出;
处理上可以使用流式加载,分批次的进行读取加载,而不是一次性全部读取,防止内存溢出
优点:
不足:
补充:
HSSFWorkbook(.xls)/ XSSFWorkbook(.xlsx),全量加载到内存XSSFSheetXMLHandler,事件驱动,逐行回调,内存恒定SXSSFWorkbook 滑动窗口(默认保留 100 行),超过窗口自动刷到临时文件OutOfMemoryError: Java heap space + 大量 Row/Cell 对象占 Old 区close()(Workbook/InputStream)、用 SXSSF 写大表、EasyExcel 替代、限制并发、监控堆使用率核心考点定位:考察对 Java IO 生态中"内存模型选择"的理解——不是"POI 会 OOM",而是"什么时候会、怎么避免"。
知识点拆解:
XSSFSheetXMLHandler,逐行回调,内存恒定dispose() 临时文件堆积-XX:+HeapDumpOnOutOfMemoryError考察方向:
rowaccessWindowSize)Files.lines 处理大文本延伸递进面试题:
@ExcelProperty 注解做字段映射,避免反射全表-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp 抓 dump;MAT 分析 dominator tree,看 Workbook/Sheet/Row 的 retained heap;结论是改 SXSSF/SAX【一句话结论】
面试官您好,POI 是 Apache 的 Excel 解析库,OOM 的根因是它默认用 DOM 模型全量加载到内存——xlsx 是 zip 压缩,解压后 DOM 通常放大 5-10 倍,100MB 文件能吃掉 1GB heap。
【三点展开】
第一,POI 有四个实现要分清楚:HSSF(.xls DOM)、XSSF(.xlsx DOM)、SXSSF(.xlsx 流式写,滑动窗口)、SAX API(.xlsx 流式读,事件驱动)。读大文件必须用 SAX,写大文件用 SXSSF,DOM 只适合小文件。
第二,内存放大是核心坑:xlsx 是 zip 格式,解压后每个 cell 在内存里是完整对象,100MB xlsx 解压后可能 1GB heap。典型 OOM 堆栈是 OutOfMemoryError: Java heap space + 大量 Row/Cell 占 Old 区。SXSSF 默认保留 100 行,超过自动刷到临时文件,用完必须调 dispose() 释放临时文件。
第三,生产上替代方案首选 EasyExcel——阿里基于 SAX 封装,1 万行内存恒定 < 10MB,API 用 @ExcelProperty 注解映射,比手写 SAX 回调简洁得多。配合堆监控 + HeapDumpOnOutOfMemoryError 抓 dump 分析 retained heap,能快速定位是不是 DOM 加载惹的祸。
【一句边界】
当然,如果是几十行的小文件做模板填充,XSSF 直接用完全没问题,不必为了流式而流式——SXSSF/EasyExcel 的 API 更啰嗦,小场景反而降低可读性。