これについていくつかの洞察を得たいと思います。
データベースからExcelファイルに読み書きするプログラムがあります。その実行は、Quartz API を使用したタイマーに基づいており、毎週火曜日にトリガーされます。問題は、1時間ごとにジョブを実行するようにスケジュールしてテストしたところ、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が無限ループで動作しているように...もっと光を当てるためにこのトピックについて、これが私のプログラムの簡単な流れです。
- ユーザーがスケジューラーを実行する
- 希望の時間に、スケジューラーがプログラムを実行します (スケジューラーと「プログラム」は 2 つの異なるプログラム/jar ファイルです。スケジューラーは単に jar を呼び出します)。
- プログラムはExcelファイルを作成することから始まります
- 次に、データベース 1 を読み取ります。データベースには 80K 行が含まれます。
- 行ごとに、特定の条件が満たされた場合、データベース 2 と 3 を読み取ります
- 次に、一度に1000個ずつarraylistオブジェクト内に保存します(メモリの問題を回避しようとしているので、バッチで保存します)
- 次に、一度に1000個ずつバッチで書きます(これが停止する部分です)
- 読み取りと書き込みが完了すると、スケジューラが再度呼び出すまで待機します...このステップに到達した場合、私は幸せなプログラマーです=)
これが私が見つけたいくつかの観察です。
- プログラムは通常、プログラムの 4 ~ 6 回目の実行で停止します (つまり、スケジューラ プログラムをノンストップで実行してから 4 ~ 6 時間後です)。
- 34千行目、24日目、15日目などのように、Excelのランダムな書き込みポイントで停止します...
- スケジューラなしでプログラムを実行すると、このエラーは発生しません。エラーなしで、1 日中手動で実行できました (実行しましたが、あまり楽しくありませんでした)。
- 出力された Excel ファイルには、サイズとして 0bytes が表示されます
- たとえば、1時間ごとに実行するようにスケジュールし、この時間に停止した場合。その後も数時間実行されますが、停止し、前回の実行とは異なる時点で停止します。
この問題の原因は何ですか。おそらくメモリリークか、もっと単純なものですか?
追加情報
他のプログラムのクラスをインポートして 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 つだけ使用しており、ジョブの後続のすべての実行はその 1 つのインスタンスから参照されるため、メモリを使い果たします。
- データベース(AS400)関連です(エクセルを書いている途中で止まってしまうので疑問です)。
- コンピューターが疲れすぎて、休憩を取ることにしました。
更新 - 2012 年 12 月 28 日
明けましておめでとうございます。
申し訳ありませんが、これに戻るのに時間がかかりました..(世界が21日に終わるのに、なぜこれに時間を無駄にするのですか。そうならなかったときはほろ苦いものでした)
私は自分のプログラムを netbeans プロファイラーでプロファイリングし、メモリ アナライザーで次の図を得ました。
最初のグラフで、プログラムが反復ごとに約 75MB のヒープ サイズを消費していることに気付きました (ピンク色で示されています)。これは、プログラムの消費メモリが反復ごとに 75 MB 増加することを意味しますか? これは、数回の反復の後、プログラムの実行に影響を与えるほど多くのメモリを消費します。現在、ヒープダンプを取得しようとしています..実行できるようになり次第、投稿します。
追加情報: Quartz のみを実行して (何もトリガーしない) プロファイラーを使用してみましたが、システムの使用率は比較的低く、反復ごとにサイズは増加しません。
私はついにヒープダンプを取得することができました。2 つのダンプを取りました。1 つ目は最初の反復が行われたときで、2 つ目は次の反復です。以下に示すように、2 つのクラスのインスタンスに大きな違いがあることに気付きました。
ありがとう!