繁体   English   中英

java.lang.OutOfMemoryError 处理大型 CSV 文件时

[英]java.lang.OutOfMemoryError While processing a Large CSV file

我正在使用 java 代码处理一个巨大的 CSV (1GB)。

我的应用程序在具有 8GB 内存的 2 核机器上运行。

我正在使用以下命令来启动我的应用程序。

java -Xms4g -Xmx6g  -cp $CLASSPATH JobSchedulerService

应用程序启动一个线程从 S3 下载 CSV 并处理它。 应用程序工作文件一段时间,但 OutOfMemoryError 处理文件中途。

我正在寻找一种可以继续处理 CSV 文件并同时保持低内存使用率的方法。

在 CSV 过程中,我正在执行以下步骤:

 //Step 1: Download FROM S3
String bucketName = env.getProperty(AWS_S3_BUCKET_NAME);
AmazonS3 s3Client = new AmazonS3Client(credentialsProvider);
S3Object s3object = s3Client.getObject(new GetObjectRequest(bucketName, key));
InputStream inputSteam =  s3object.getObjectContent();   //This Stream contains about 1GB of data

//Step 2: Parse CSV to Java
ObjectReader oReader = CSV_MAPPER.readerFor(InboundProcessing.class).with(CSV_SCHEMA);
try (FileOutputStream fos = new FileOutputStream(outputCSV, Boolean.FALSE)) {
    SequenceWriter sequenceWriter = CsvUtils.getCsvObjectWriter(InboundProcessingDto.class).writeValues(fos);
    MappingIterator<T>  mi = oReader.readValues(inputStream)

    while (mi.hasNextValue()) {
        InboundProcessing inboundProcessing = mi.nextValue();
        inboundProcessingRepository.save(inboundProcessing);   // this is Spring JPA Entity Save operation. (Almost 3M records  so 3M calls)                    
        sequenceWriter.write(inboundProcessingDto);  // this is writing to a CSV file on local file system which is uploaded to S3 in next Step
    }
} catch (Exception e) {
    throw new FBMException(e);
}

1) 将大文件拆分为小文件。

2) 依次或并行处理每个文件。

检查小尺寸拆分文件的链接: https : //stackoverflow.com/a/2356156/8607192

或者

使用 Unix 命令“split for split based on size”。

我找到了 OOM 的原因。 虽然我正在以正确的方式阅读文件。 处理完后,逐行读取文件并丢弃旧行。 所以这不会造成问题。

问题是当我将相同的内容写入数据库时​​。

我的代码在事务块中运行,因为在事务完成之前不会释放实体。 简而言之,所有 3M 实体都保存在内存中,直到提交事务。

一旦我在我的可疑对象中添加了 finalize 方法,我就能够得出这个结论。 我所看到的只是 DTOS(临时 Pojo)以非常快的速度被丢弃,但甚至没有丢弃一个实体。 最后一下子所有的实体都丢弃了。

您还没有关闭 InputStream inputSteam

关于 s3object.getObjectContent() 获取包含此对象内容的输入流。

注意:该方法是一个简单的 getter,实际上并不创建流。 如果您检索 S3Object,则应尽快关闭此输入流,因为对象内容不会缓存在内存中,而是直接从 Amazon S3 流式传输。 此外,未能关闭此流可能会导致请求池被阻塞。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM