我想对此有一些见解。
我有一个从数据库读取和写入 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正在无限循环上工作一样...为了提供更多信息关于这个主题,这是我的程序的简要流程。
- 用户执行调度程序
- 在所需的时间,调度程序执行程序(调度程序和“程序”是两个不同的程序/jar 文件。调度程序只是调用 jar)
- 程序首先创建 Excel 文件
- 然后读取数据库1。该数据库包含80K行
- 对于每一行,如果满足某个条件,则读取数据库 2 和 3
- 然后它将它一次存储在一个 arraylist 对象中(我试图避免任何内存问题,所以我批量存储它)
- 然后我分批编写,一次 1000 个以求出色(这是它停止的部分)
- 完成读写后,它会等待调度程序再次调用它...如果到达这一步,我就是一个快乐的程序员 =)
以下是我发现的一些观察结果;
- 程序通常在程序第 4 到 6 次执行时停止(即在调度程序不间断运行 4 或 6 小时后)
- 它停止在 Excel 中的随机写入点,例如第 34000 行、第 24 行或第 15 行等等等......
- 当我在没有调度程序的情况下执行程序时,不会发生此错误。我可以手动执行一整天(我做到了,这不是很有趣),没有任何错误。
- 输出 Excel 文件的大小显示为 0 字节
- 例如,如果我安排它每小时运行一次,但在这一小时它停止了。它仍将在接下来的几个小时内运行,但会停止,并且与前一次运行相比会在不同的点停止。
可能是什么原因导致了这个问题。也许是内存泄漏或更简单的原因?
附加信息
我通过导入其他程序的类并将其作为作业运行来实现 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();
}
}
有没有可能;
- 该应用程序耗尽了我的内存并崩溃了
- 我在 Quartz 作业中仅使用“程序”的一个实例,该实例在作业第一次运行时初始化,并且该作业的所有后续执行都从该实例引用,从而最大化了内存。
- 它与数据库(AS400)相关(我怀疑,因为它在写入 Excel 时停止)。
- 计算机变得太累了,决定休息一下。
更新 - 12/28/2012
新年快乐伙计们/姑娘们!!
抱歉,我花了一些时间才回到这个话题..(当世界将在 21 号结束时,为什么还要在这上面浪费时间呢?当世界没有结束时,我感到苦乐参半)
我使用 netbeans profiler 分析了我的程序,并使用内存分析器得到了以下数据
我在第一张图中注意到,我的程序每次迭代都会消耗大约 75MB 的堆大小(如粉色阴影所示)。这是否意味着程序每次迭代消耗的内存增加了 75mb?经过几次迭代后,将消耗大量内存,从而影响程序的执行。我目前正在尝试进行堆转储。一旦我设法让它运行,我就会立即发布它。
附加信息:我尝试使用仅运行 Quartz 的探查器(不触发任何内容),系统使用率相对较低,并且每次迭代的大小不会增加。
我终于设法得到了堆转储。我进行了两次转储,第一次是第一次迭代发生时,第二次是下一次迭代时。我注意到我的两个类的实例之间存在很大差异,如下所示
Thanks!