【发布时间】:2020-04-24 06:03:26
【问题描述】:
我有一个 Spring 批处理作业,其中仅包含一个步骤,即使用 FlatFileItemReader 读取 CSV 文件(包含大约 2000 行)并将对象写入数据库。我有自己的自定义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);
}
【问题讨论】:
-
无论对象是否立即释放,垃圾收集器都会做实际释放内存的工作。它将决定何时运行,以及将什么留在原地与实际释放 - 根据运行时情况,有时决定是将垃圾留在原地。
-
问题是,如果我使用更大的输入(140k 行)测试作业并将块大小设置为 1000,将堆内存大小限制为 64MB 以强制 GC操作,在处理前 3 个批次后,我得到一个
java.lang.OutOfMemoryError: GC overhead limit exceeded.所以看起来,属于一个批次的实例在完成该批次的作业后没有被清理。这是预期的行为吗? -
处理过的块的项目应该被垃圾收集(我添加了一个包含更多细节的答案)。您确定您的自定义
BeanWrapperFieldSetMapper(或其他东西)在整个作业执行期间没有保存项目吗? -
我在问题描述中添加了我的 BeanWrapperFieldSetMapper 的实现。
-
您好,我也有同样的问题,请问您找到答案了吗?
标签: java spring spring-boot spring-batch