缘起:IDEA 提示内存不足,生成 idea use report,搜到一篇文章
如何使用intellij-idea内存分析工具排查内存泄漏问题 - 简书 (jianshu.com)
示例中,OutOfMemoryError 的原因,
- 最大原因是:内存配置太小
- 其次才是, 和 list=new ArrayList() 比 list.clear()更耗内存的问题
list=new ArrayList() (回收旧list 内存空间,分配新list 内存空间)
list.clear()(array[i]=null,复用 list 内存空间)
由 list 清空的方式,想起 EasyExcel 示例代码中,使用 分配操作使用 Field list = new ArrayList 方式,一时搞不清 EasyExcel Field list 是否能确保垃圾回收,回答为是
Q:SpringBoot IOC 容器管理 单例类,但为什么 EasyExcel 没有加入 SpringBoot 的管理?
A:EasyExcel 、Slf4J 和 SpringBoot 的处理方式是一样的,静态工厂作为入口,提供简单、一致且易于使用的接口,同时隐藏底层实现的细节
// 方法内
EasyExcel.read(file.getInputStream(), reqClz, customListener)
.sheet()
.headRowNumber(Objects.isNull(headRowNumber) ? 1 : headRowNumber)
.doRead();
// Field
private static final Logger LOG = LoggerFactory.getLogger(SFTPUtil.class);
// 方法内
LOG.error("SFTPUtil.connect error",e);
// SpringBoot 启动类
@SpringBootApplication
public class MyApplication {
public static ConfigurableApplicationContext applicationContext;
public static void main(String[] args) {
applicationContext = SpringApplication.run(ReconciliationApplication.class, args);
}
}
Q:EasyExcel 如何确保 一次性千万行数据的垃圾回收?
A:
- EasyExcel 的工作:
工厂 EasyExcelFactory 给 每个 Excel Sheet 构建一个上下文 ExcelReaderSheetBuilder,
读取器 ExcelReader 使用 执行器 ExcelExecutor 解析 XML 格式数据,解析事件处理器 DefaultAnalysisEventProcessor 获取单行数据
监听器ModelEventListener 用 转换器 Converter 转换字段类型,再调用 自定义监听器 AnalysisEventListener 暂存分批保存Excel数据
ref:
https://www.yuque.com/easyexcel/doc/gpaz17
easyexcel的源码简单分析_12476320的技术博客_51CTO博客
- 按行处理 Excel 数据,在常用的读取校验保存场景下,AnalysisEventListener类 内必须定义一个 List属性 暂存解析到的数据,以减少数据库IO
不加入Spring 容器管理,List属性 更安全易用,每次使用new 一个 AnalysisEventListener,也更便于 一次性千万行数据 的垃圾回收
引申:
SpringBoot RESTful 响应的大量数据,如 List 包装的那些数据,如何确保可以被垃圾回收?
解释:这些数据都是方法内的数据,在 List 不会再被传递,即 List 序列化成 JSON 的方法调用结束后,方法的局部变量和栈帧将被销毁,这也包括对 List 实例的引用。垃圾收集器会找出不被引用的对象,并回收这些不被引用对象占用的内存空间