【问题标题】:Java Excel POI stops after multiple execution by quartz石英多次执行后Java Excel POI停止
【发布时间】:2012-11-21 08:12:31
【问题描述】:

我想对此有一些见解。

我有一个从数据库读取和写入 excel 文件的程序。它的执行基于使用 Quartz api 的计时器,并在每周的每个星期二触发。问题是,当我通过安排它每小时执行一次作业来测试它时,程序在编写 excel 文件的过程中执行了几次后突然停止。这是我写的excel代码。

try {
        FileInputStream file = new FileInputStream(excelFile);
        POIFSFileSystem myFileSystem = new POIFSFileSystem(file);
        HSSFWorkbook workbook = new HSSFWorkbook(myFileSystem);
        HSSFSheet worksheet = workbook.getSheetAt(0);
        this.cellStyle00 = workbook.createCellStyle();
        HSSFDataFormat df = workbook.createDataFormat();
        this.cellStyle00.setDataFormat(df.getFormat("00"));

for(int i = 0;i<Access.size();i++){
         AccessorMethods SetGet = (AccessorMethods)
                    InstlibAccessor.get(i);

    HSSFRow row = worksheet.createRow(worksheet.getPhysicalNumberOfRows());
    HSSFCell cell = row.createCell(0);

    cell.setCellValue(new Double(SetGet.getOne()));
    cell.setCellStyle(cellStyle00);


  //other set value codes....

}
FileOutputStream fileOut = new FileOutputStream(fileName + ".xls");
workbook.write(fileOut);
 fileOut.flush();
 fileOut.close(); 

 //catch statements follow
 //end

命令行输出和netbeans输出不表示任何错误,如内存不足等。程序没有结束..它只是,停止..就像jvm正在无限循环中工作......到更多地阐明这个主题,这是我的程序的简要流程。

  1. 用户执行调度器
  2. 调度程序在所需时间执行程序(调度程序和“程序”是两个不同的程序/jar 文件。调度程序只是调用 jar)
  3. 程序从创建excel文件开始
  4. 然后读取数据库1。数据库包含80K行
  5. 对于每一行,如果满足某个条件,则读取数据库2和3
  6. 然后一次将其存储在 arraylist 对象 1000 中(我试图避免任何内存问题,所以我批量存储它)
  7. 然后我分批写,一次 1000 个以 excel (这是它停止的部分)
  8. 它完成读写后,等待调度器再次调用它...如果达到这一步我是一个快乐的程序员=)

以下是我发现的一些观察结果;

  1. 程序通常在程序执行的第 4 到第 6 次停止(即在不间断运行调度程序 4 或 6 小时后)
  2. 它会在 Excel 中的随机写入点停止,例如在第 34 千行或第 24 或第 15 行等...
  3. 当我在没有调度程序的情况下执行程序时不会发生此错误。我可以整天手动执行它(我做到了,这不是很有趣),没有任何错误。
  4. 输出的 excel 文件显示大小为 0bytes
  5. 例如,如果我安排它每小时运行一次,但在这一小时内它停止了。它仍会在接下来的几个小时内运行,但会停止,并在与上一次运行相比不同的点停止。

是什么导致了这个问题。可能是内存泄漏或更简单的原因?

其他信息

我通过导入其他程序的类来实现 Quartz 调度程序并将其作为作业运行。这是触发器的代码

JobDetail job = newJob(ExtractorSchedulerJobUtilTester.class)
            .withIdentity("job1", "group1")
            .build();

    CronTrigger trigger = newTrigger()
            .withIdentity("trigger1", "group1")
            .withSchedule(cronSchedule("0 0/2 * 1/1 * ? *"))
            .build();

    Date ft = sched.scheduleJob(job, trigger);
        sched.start();

和工作

public class ExtractorSchedulerJobUtilTester implements Job {
    public void execute(JobExecutionContext context)
        throws JobExecutionException {
    theProgram program= new theProgram();

    program.main();

    JobKey jobKey = context.getJobDetail().getKey();
    }
}

有可能吗?

  1. 应用程序正在耗尽我的内存并崩溃
  2. 我只在我的 Quartz 作业中使用了一个“程序”实例,该实例在作业的第一次运行时被初始化,并且作业的所有后续执行都是从该实例引用的,因此会耗尽内存。
  3. 它与数据库 (AS400) 相关(我怀疑是因为它在编写 excel 时停止了)。
  4. 电脑太累了,决定休息一下。

更新 - 2012 年 12 月 28 日

男/女新年快乐!!

抱歉,我花了一些时间才重新开始。(既然世界将在 21 日结束,为什么还要浪费时间在这上面。如果没有,那真是苦乐参半)

我用 netbeans profiler 分析了我的程序,并用内存分析器得到了以下数据

我注意到在第一张图中,我的程序每次迭代都会消耗大约 75MB 的堆大小(如粉红色阴影所示)。这是否意味着程序每次迭代消耗的内存增加了 75mb?在几次迭代之后,这将消耗大量内存,从而影响程序的执行。我目前正在尝试进行堆转储。一旦我设法让它运行,我会发布它。

附加信息:我尝试使用仅运行 Quartz 的分析器(不会触发任何东西),系统使用率相对较低,每次迭代的大小都不会增加。

我终于设法获得了堆转储。我进行了 2 次转储,第一次是第一次迭代发生时,第二次是下一次迭代。我注意到我的两个类的实例之间存在很大差异,如下所示

谢谢!

【问题讨论】:

  • 分析有什么指导吗?你每次都启动一个新的虚拟机吗?另请参阅answer?
  • 调度器如何执行程序?使用java 命令行启动一个新的虚拟机还是只导入程序的Java 类并运行?尝试让调度程序每 5 或 10 分钟运行一次以进行调试。查看此问题 (stackoverflow.com/questions/337793/…) 以了解如何转储 JVM 崩溃日志。
  • @AlexCheng。我只是导入该类并将其作为作业运行..
  • 使用 jdk 的 jstack 工具创建一些线程转储。当程序挂起时,您应该能够确定您的线程在做什么。
  • 从您提到的内容来看,excel 代码看起来还不错。我对触发部分持怀疑态度。通过制作自己的小型调度程序来尝试它。即不是 Quartz,让一个线程运行任务并休眠 2 分钟,然后继续并重复大约 20 次。如果一切正常,那么问题出在 Quartz

标签: java profiling apache-poi quartz-scheduler


【解决方案1】:

经过大量的诅咒、祈祷和搜索,我想我已经找到了一个可能的解决方案。我所做的是在我的 Quartz 作业课程的末尾添加 System.gc();。因此,每次程序完成工作时都会调用垃圾收集。这只是一个可能的解决方案,而不是一个具体的答案,因为我仍然在消耗大量的堆内存(我相信在我的代码混乱的某个地方仍然存在一些内存泄漏)。但是,使用System.gc();,我的消费量要少得多。我只是不确定这是怎么发生的。从逻辑上讲,我认为 GC 只会影响内存分配而不影响程序的内存性能。见下图;上图是有 GC 的图,下图是没有 GC 的图。

如您所见,带有 GC 的那个占用的堆内存比没有那个的要少。我假设内存使用量与 GC 相同,但是一旦调用 GC,使用的堆空间就会下降。在出现更好的答案之前,我将暂时使用此解决方案。

【讨论】:

  • 哈哈,伙计,我正在使用 c# 它也适用于我,9 年的神圣代码 :) 谢谢
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-22
  • 2011-03-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多