首页 > 解决方案 > 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);
    }

标签: javaspringspring-bootspring-batch

解决方案


这留给垃圾收集器。与此问题相关的相关代码部分位于ChunkOrientedTasklet中。在最基本的形式中ChunkOrientedTasklet,有两个调用:

Chunk<I> inputs = chunkProvider.provide(contribution);
chunkProcessor.process(contribution, inputs);

ChunkProvider使用ItemReader来阅读commit-interval项目(如果项目阅读器返回,则使用更少)null。以及用于处理和编写项目的ChunkProcessor用途:ItemProcessorItemWriter

Chunk<O> outputs = transform(contribution, inputs);
write(contribution, inputs); // details of adjustments of output omitted here

此过程重复运行,直到数据源耗尽。因此,当 GC 启动时(因为变量inputs/outputs被重新使用),处理过的块的项目应该被垃圾收集,除非在整个作业执行期间有东西将它们保存在内存中。


推荐阅读