java - Spring Batch 是否在处理完每个批次后释放堆内存?
问题描述
我有一个 Spring 批处理作业,其中仅包含一个步骤,该步骤使用 a 读取 CSV 文件(包含大约 2000 行)FlatFileItemReader
并将对象写入数据库。我有自己的自定义BeanWrapperFieldSetMapper
将行映射到对象。块大小设置为 50,因此我期望在从每个批次(50 个对象)中写入对象后,这些对象的堆内存将被释放。
由于我正在利用批处理,我希望在每个给定时间只有 50 个 CreditCardDebt 对象。但相反,在处理最后一批时,我发现堆内存包含 2000 个 CreditCardDebt 对象。
我错过了什么?
我的 BeanWrapperFieldSetMapper 实现:
@Component("CREDIT_CARD_DEBT_FIELD_SET_MAPPER_TEST")
public class TestDebtFieldSetMapper extends BeanWrapperFieldSetMapper<CreditCardDebt> {
public TestDebtFieldSetMapper() {
super.setPrototypeBeanName("CREDIT_CARD_DEBT_FIELD_SET_MAPPER_TEST");
}
@NonNull
@Override
public CreditCardDebt mapFieldSet(FieldSet fieldSet) {
CreditCardDebt creditCardDebt = new CreditCardDebt();
creditCardDebt.setAccount(fieldSet.readString(0));
creditCardDebt.setCardholderId(fieldSet.readString(1));
creditCardDebt.setDueDate(convertToLocalDateViaInstant(fieldSet.readString(2)));
creditCardDebt.setDaysPastDue(fieldSet.readInt(3));
creditCardDebt.setOverdueAmount(fieldSet.readDouble(4));
creditCardDebt.setDirectDebitMinimumPayment(fieldSet.readDouble(5));
creditCardDebt.setDirectDebitBalance(fieldSet.readDouble(6));
creditCardDebt.setDirectDebitStatus(fieldSet.readChar(7));
creditCardDebt.setDirectDebitType(DirectDebitType.valueOf(fieldSet.readString(8)));
creditCardDebt.setCreatedDate(LocalDateTime.now());
creditCardDebt.setFileName("BAL");
return creditCardDebt;
}
private LocalDate convertToLocalDateViaInstant(String dateToConvert) {
DateTimeFormatter formatters = DateTimeFormatter.ofPattern("yyyyMMdd");
return LocalDate.parse(dateToConvert, formatters);
}
解决方案
这留给垃圾收集器。与此问题相关的相关代码部分位于ChunkOrientedTasklet中。在最基本的形式中ChunkOrientedTasklet
,有两个调用:
Chunk<I> inputs = chunkProvider.provide(contribution);
chunkProcessor.process(contribution, inputs);
ChunkProvider
使用ItemReader
来阅读commit-interval
项目(如果项目阅读器返回,则使用更少)null
。以及用于处理和编写项目的ChunkProcessor
用途:ItemProcessor
ItemWriter
Chunk<O> outputs = transform(contribution, inputs);
write(contribution, inputs); // details of adjustments of output omitted here
此过程重复运行,直到数据源耗尽。因此,当 GC 启动时(因为变量inputs
/outputs
被重新使用),处理过的块的项目应该被垃圾收集,除非在整个作业执行期间有东西将它们保存在内存中。
推荐阅读
- next.js - 组件定义缺少显示名称eslintreact/display-name
- selenium - 使用 Selenium C# DevTools 如何使用 c# 捕获 f12 选项(网络)
- excel - 在 Excel 中计算电力塔的困难
- entity-framework - 在 Razor 页面中添加脚手架项目时出错
- django - 如何在序列化程序中获取所有字段名称
- unity3d - Unity3D - 将第三人称视角限制为仅查看 FPS 视图可以看到的内容
- javascript - 如何在 js discord bot 开发中使用 cookie
- c++ - C++静态对象不保存数组属性值
- pandas - 为什么带有 adlfs 的 dask read_csv() 会遇到内存问题?
- java - 位图无法正确解码代表文件数据的 byteArray