2010-02-26 4 views
5

Я использую программу для передачи данных из базы данных в файл Excel. Он отлично работает в начале, а затем становится все медленнее, и, наконец, он заканчивается из памяти и появляется следующая ошибка: «java.lang.OutOfMemoryError: Java heap space ...».Почему моя программа становится все медленнее и медленнее?

Проблема может быть решена путем добавления jvm heap sapce. Но вопрос в том, что он тратит слишком много времени на выполнение программы.

Через несколько минут он закончил цикл с 4 секундами, который можно завершить с 0,5 секунды в начале. Я не могу найти решение, чтобы он всегда работал с определенной скоростью.

Это проблема с моим кодом?

Любые подсказки по этому вопросу?

Вот код:

public void addAnswerRow(List<FinalUsers> finalUsersList,WritableWorkbook book){ 

    if (finalUsersList.size() >0) { 
    try { 
     WritableSheet sheet = book.createSheet("Answer", 0); 
     int colCount = 0; 
     sheet.addCell(new Label(colCount++,0,"Number")); 
     sheet.addCell(new Label(colCount++,0,"SchoolNumber")); 
     sheet.addCell(new Label(colCount++,0,"District")); 
     sheet.addCell(new Label(colCount++,0,"SchoolName")); 
     sheet.setColumnView(1, 15); 
     sheet.setColumnView(3, 25); 

     List<Elements> elementsList = this.elementsManager.getObjectElementsByEduTypeAndQuestionnaireType(finalUsersList.get(0).getEducationType().getId(),  this.getQuestionnaireByFinalUsersType(finalUsersList.get(0).getFinalUsersType().getId())); 

     Collections.sort(elementsList, new Comparator<Elements>(){ 

      public int compare(Elements o1, Elements o2) { 

      for(int i=0; i< (o1.getItemNO().length()>o2.getItemNO().length()? o2.getItemNO().length(): o1.getItemNO().length());i++){ 
        if (CommonFun.isNumberic(o1.getItemNO().substring(0, o1.getItemNO().length()>3? 4: o1.getItemNO().length()-1)) && !CommonFun.isNumberic(o2.getItemNO().substring(0, o2.getItemNO().length()>3? 4: o2.getItemNO().length()-1))){ 
       return 1; 
        } 
       if (!CommonFun.isNumberic(o1.getItemNO().substring(0, o1.getItemNO().length()>3? 4: o1.getItemNO().length()-1)) && CommonFun.isNumberic(o2.getItemNO().substring(0,o2.getItemNO().length()>3? 4:o2.getItemNO().length()-1))){ 
       return -1; 
       } 
       if (o1.getItemNO().charAt(i)!=o2.getItemNO().charAt(i)){ 

        return o1.getItemNO().charAt(i)-o2.getItemNO().charAt(i); 
       } 
      } 
      return o1.getItemNO().length()> o2.getItemNO().length()? 1:-1; 
     }}); 

     for (Elements elements : elementsList){ 
      sheet.addCell(new Label(colCount++,0,this.getTitlePre(finalUsersList.get(0).getFinalUsersType().getId(), finalUsersList.get(0).getEducationType().getId())+elements.getItemNO()+elements.getItem().getStem())); 
     } 

     int sheetRowCount =1; 
     int sheetColCount =0; 

     for(FinalUsers finalUsers : finalUsersList){ 

      sheetColCount =0; 

      sheet.addCell(new Label(sheetColCount++,sheetRowCount,String.valueOf(sheetRowCount))); 
      sheet.addCell(new Label(sheetColCount++,sheetRowCount,finalUsers.getSchool().getSchoolNumber())); 
      sheet.addCell(new Label(sheetColCount++,sheetRowCount,finalUsers.getSchool().getDistrict().getDistrictNumber().toString().trim())); 
      sheet.addCell(new Label(sheetColCount++,sheetRowCount,finalUsers.getSchool().getName())); 

      List<AnswerLog> answerLogList = this.answerLogManager.getAnswerLogByFinalUsers(finalUsers.getId()); 


      Map<String,String> answerMap = new HashMap<String,String>(); 

      for(AnswerLog answerLog :answerLogList){ 
      if (answerLog.getOptionsId() != null) 
      { 
       answerMap.put(answerLog.getElement().getItemNO(), this.getOptionsAnswer(answerLog.getOptionsId())); 
      }else if (answerLog.getBlanks()!= null){ 

       answerMap.put(answerLog.getElement().getItemNO(), answerLog.getBlanks()); 
      }else{ 

       answerMap.put(answerLog.getElement().getItemNO(), answerLog.getSubjectiveItemContent()); 
      } 
      } 
      for (Elements elements : elementsList){ 

      sheet.addCell(new Label(sheetColCount++,sheetRowCount,null==answerMap.get(elements.getItemNO())?"0":answerMap.get(elements.getItemNO()))); 

      } 

     sheetRowCount++; 
     } 

     book.write(); 
     book.close(); 

    } catch (IOException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } catch (RowsExceededException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } catch (WriteException e) { 

     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 

}}

+0

(Продолжение комментария ниже) Вам не нужно объяснять подробно .. Например, «Я беру два листа, что оба имеют общий ключ (studentId или что-то ??) и присоединение к ним "или что-то в этом роде. Затем мы можем порекомендовать вам использовать сортировку merge для сортировки этих листов сначала, используя дисковое пространство, а затем вы можете выполнять итерацию по обоим листам, не используя пучок памяти ... –

ответ

9

Где вы создаете объекты и сохранения достижимые ссылки на них.

Возможно, вы добавляете объекты в коллекцию и никогда не удаляете их ... поэтому коллекция просто растет, пока вы не исчерпаете память. Когда вы приближаетесь к максимальному размеру кучи, сборщик мусора чрезмерно облагается налогом, чтобы найти свободную память для реорганизации вещей, и программа становится экспоненциально медленнее, чем ближе вы достигаете предела.

Кроме того, возможно, вы забыли закрыть какой-либо объект (ы) каждый раз, например, в своей книге.

+0

Звучит так, что его нельзя избежать. создавать объекты для хранения данных из базы данных и времени, когда работа GC не показана. Также в конце книги рабочая тетрадь закрыта: book.close() – RedWolf

+0

Код трудно понять ... можете ли вы кратко объяснить, чего вы пытаетесь достичь? Тогда мы могли бы увидеть, действительно ли невозможно (с огромной коллекцией) избежать (если этого действительно не избежать, вы все равно можете использовать диск, так что не волнуйтесь ..) –

+0

@ Zwei: You может захотеть переместить свой комментарий на вопрос ... Я не думаю, что RedWolf будет уведомлен, если это под моим ответом. –

2

Я очень подозреваю, что в вашей программе есть утечка памяти. Используйте профайлер, например JProfiler или YourKit, для обнаружения утечки памяти. Может, вы забыли закрыть WritableWorkbook?

http://jexcelapi.sourceforge.net/resources/javadocs/current/docs/jxl/write/WritableWorkbook.html

+0

Рабочая тетрадь закрыта в конце. Я собираюсь отметить тест памяти. :) – RedWolf

1

Когда приложение запущено из кучи пространства, он будет принимать все больше и больше времени в GC пытается вернуть себе место, прежде чем в конце концов сдаться и бросали OutOfMemoryError. Я рекомендую делать следующее:

  • добавить опцию -XX:+UseGCOverheadLimit JVM, чтобы вызвать JVM сбой раньше, когда он уходит из памяти.

  • использовать профайлер памяти для поиска возможных утечек памяти

  • , если вы не можете найти любые утечки, просто увеличить размер кучи.

Если вы все еще получаете эффекты замедления с большей кучей, проблема может быть связана с использованием используемых алгоритмов. В этом случае вам нужно использовать профилировщик выполнения, чтобы выяснить, где ваше приложение тратит большую часть своего времени.

[Теория: Если ваш addAnswerRow вызывается повторно, проблема может быть связана с многократным открытием файла электронной таблицы Xcel, который увеличивается каждый с каждым вызовом addAnswerRow. Возможно, каждый раз, когда вы открываете файл, он полностью загружается в память.]

+0

Файл excel создается, когда addAnswerRow() вызывается один раз. Это мой false, который я назвал функцией как addAnswerRow(). Его следует называть createAnswerExcel(). Это называется много раз. Я последую вашему предложению. :) – RedWolf

0

Используйте опцию -verbose: gc JVM, чтобы легко проверить, вызвано ли замедление тем, что происходит в GC.

0

Увеличение размера кучи может помочь. Вы можете попробовать установить минимальный и максимальный размер кучи, включив аргументы -Xms и -Xmx. Следующая команда установит минимальный размер кучи как 512 МБ и максимальную кучу как 1024 МБ.

ява -Xms512m -Xmx1024m MyProgram