春季批处理作业不会发布内存



我并行运行约18.000个春季作业,每个作业都有一个步骤。每个步骤都包括从文件中读取,转换和操纵这些值并将其写入Mongo和MySQL数据库,这并不常见。所有工作完成后,内存消耗保持在20GB 使用的20GB,并且留在那里。我构造我的春季批处理成员如下:

@Autowired
public ArchiveImportManager(final JobRepository jobRepository, final BlobStorageConfiguration blobConfiguration,
        final JobBuilderFactory jobBuilderFactory, final StepBuilderFactory stepBuilderFactory,
        final ArchiveImportSettings settings) {
    this.jobBuilderFactory = jobBuilderFactory;
    this.stepBuilderFactory = stepBuilderFactory;
    this.jobLauncher = new SimpleJobLauncher();
    final ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
    threadPoolTaskExecutor.setCorePoolSize(THREAD_POOL_SIZE);
    threadPoolTaskExecutor.setMaxPoolSize(THREAD_POOL_SIZE);
    threadPoolTaskExecutor.setQueueCapacity(THREAD_POOL_QUEUE);
    threadPoolTaskExecutor.initialize();
    this.jobLauncher.setTaskExecutor(threadPoolTaskExecutor);
    this.jobLauncher.setJobRepository(jobRepository);
}

我创建一个作业如下:

private Job createImportJob(final ArchiveResource archiveResource, final int current, final int archiveSize) {
    final String name = "ImportArchiveJob[" + current + "|" + archiveSize + "]"
            + new Date(System.currentTimeMillis());
    final Step step = this.stepBuilderFactory
            .get(name)
            .<ArchiveResource, ArchiveImportSaveData> chunk(1)
            .reader(getReader(archiveResource, current, archiveSize))
            .processor(getProcessor(current, archiveSize))
            .writer(getWriter(current, archiveSize))
            .build();
    return this.jobBuilderFactory
            .get(name)
            .flow(step)
            .end()
            .build();
}

并在循环中启动所有作业:

private void startImportJobs(final List<ArchiveResource> archives) {
    final int size = archives.size();
    for (int i = 0; i < size; i++) {
        final ArchiveResource ar = archives.get(i);
        final Job j = createImportJob(ar, i, size);
        try {
            this.jobLauncher.run(j, new JobParametersBuilder()
                    .addDate("startDate", new Date(System.currentTimeMillis()))
                    .addString("progress", "[" + i + "|" + size + "]")
                    .toJobParameters());
        } catch (final JobExecutionAlreadyRunningException e) {
            log.info("Already running", e);
        } catch (final JobRestartException e) {
            log.info("Restarted", e);
        } catch (final JobInstanceAlreadyCompleteException e) {
            log.info("ALready completed", e);
        } catch (final JobParametersInvalidException e) {
            log.info("Parameters invalid", e);
        }
    }
}

我是否必须以某种方式释放记忆或删除作业后?我不明白为什么记忆消耗保持很高。

最好的问候

从HTOP中获取该信息并从中获取任何信息并不是一个好主意。这是因为Java内存管理。

Java从操作系统中分配内存并在内部管理该内存。这全都连接到诸如垃圾收集和世代内存模型之类的术语。

基本上,如果您通过在应用程序中删除对这些对象的引用来释放内存,则不会立即设置内存。只有当Java分配的内存已满时,才会触发垃圾收集周期。该周期不会(一定)释放针对OS的内存。第一步将使您的Java程序可用,同时仍然坚持使用OS。

如果Java VM中的启发式词确定,您分配了太多的内存,它将向操作系统释放内存,但这是您不应依靠的。

这就是为什么您仍然会看到Java过程保留的20G。而且,如果没有仔细观察该应用程序,您甚至都不知道该内部内部释放或填满了死对象。

如果您想更好地了解应用程序的内存脚印,我建议您执行以下操作:诸如JConsole或JvisualVM之类的工具(在这里您需要Visual GC插件)允许您检查内存的内部。由Java VM分配。在该内存中,对于称为旧或终身任期的内存区域,与您的问题无关(如果您很好奇,则其他所有内容都与您的问题无关。如果您想触发垃圾收集以删除已经死亡(但尚未清理的对象),要么在您的应用程序中明确调用System.gc(),要么通过JConsole或JvisualVM触发它(都有一个按钮可以这样做)。垃圾收集后直接的内存消耗是您当前正在寻找的数字。

相关内容

  • 没有找到相关文章

最新更新