2012-11-21 38 views
5

我想對此有幾點見解。Java Excel POI在石英多次執行後停止

我有一個程序,可以讀取和寫入數據庫到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. 它然後將其存儲在內部ARRA (我試圖避免任何內存問題,所以我按批次存儲它)
  7. 然後,我一次寫它,1000一次超過(這是它停止的部分)
  8. 它後完成閱讀和寫作,它等待,直到調度器再次調用它...如果它達到這一步,我是一個快樂的程序員=)

這裏是我發現的一些意見;

  1. 該程序通常會停止在第4到程序的第六執行(這是後4或6小時運行調度器程序不停)
  2. 它停止在寫入在Excel中的隨機點像在34,000行或24或15等等等等等等
  3. 當我沒有調度程序執行程序時,不會發生此錯誤。我可以整天手動執行它(我確實,這不是很有趣),沒有任何錯誤。
  4. 輸出Excel文件顯示0字節大小
  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. 我只在其中在工作的第一次運行和作業的所有後續執行初始化我石英作業中使用「程序」的一個實例崩潰從一個實例引用,從而最大化內存。
  3. 它與數據庫(AS400)相關(我懷疑它是因爲它在寫入excel時停止)。
  4. 電腦變得太累了,決定休息一下。

更新 - 2012年12月28日

新年快樂傢伙/三角旗號!

對不起,我花了一些時間來找回這個。(在此何必浪費時間當世界上21會結束。這是苦樂參半的,當它沒有)

我異型我與NetBeans配置程序,並與內存分析器

memory dump

我在我的程序消耗約75MB的堆大小爲每個迭代(由粉紅色光所示)的第一張圖發現了下面的圖。這是否意味着程序的消耗內存每次迭代增加75mb?經過幾次迭代後,會消耗太多的內存,從而影響程序的執行。我目前正在嘗試堆轉儲..我會盡快讓它運行。

附加信息:我嘗試使用只有Quartz運行的探查器(不會觸發任何事情),並且系統使用率相對較低,並且每次迭代的大小不會增加。

我終於設法得到堆轉儲。我做了2次轉儲,第一次是第一次迭代發生,第二次是下一次迭代。我注意到,有低於

hash dump

感謝所示的我的兩個類新的實例之間有很大的區別!

+1

分析的任何指導?你每次都開始新的虛擬機嗎?另請參閱此[答案](http://stackoverflow.com/a/6310284/230513)? – trashgod

+2

調度程序如何執行程序?使用'java'命令行啓動新的虛擬機,或者只導入程序的Java類並運行?嘗試使調度程序每5或10分鐘運行一次以進行調試。檢出此問題(http://stackoverflow.com/questions/337793/can-i-force-generation-of-a-jvm-crash-log-file)知道如何轉儲JVM崩潰日誌。 –

+0

@AlexCheng。我只是導入課堂並將其作爲工作來運行.. – ides

回答

0

經過大量的詛咒,祈禱和尋找,我想我已經找到了一個可能的解決方案。我所做的是在我的Quartz工作課程結束時添加System.gc();。因此,每次程序完成作業時調用垃圾收集。這只是一個可能的解決方案,而不是一個具體的答案,因爲我仍然吃掉了大量的堆內存(我相信在我的代碼混亂的地方仍然有一些內存泄漏)。但是,與System.gc();我消耗少得多。我只是不確定這是怎麼發生的。從邏輯上講,我認爲GC只會影響內存分配,而不會影響程序的內存性能。見下圖;最上面的圖是帶GC的,而底部是沒有的。

enter image description here

正如你可以看到一個與GC正在消耗比一個沒有堆內存更少。我認爲內存使用量仍然與GC相同,但一旦調用GC,使用的堆空間將會減少。現在我將使用此解決方案,直到出現更好的答案。