Я использую программу для отправки данных от базы данных до файла Excel. Это хорошо работает вначале и затем становится все более медленно, наконец это исчерпывает память и следующую ошибку ocurrs: "java.lang. OutOfMemoryError: пространство "кучи" Java...".
Проблема может быть разрешена путем добавления jvm пространства "кучи". Но вопрос состоит в том, что это проводит слишком много времени для окончания программы.
После нескольких минут это закончило цикл с 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();
}
} }
Где-то вы создаете объекты и сохраняете на них доступные ссылки.
Вы, вероятно, добавляете объекты в коллекцию и никогда не удаляете их ... поэтому коллекция просто увеличивается, пока у вас не закончится память. По мере того, как вы приближаетесь к максимальному размеру кучи, сборщик мусора перегружается, чтобы найти свободную память для реорганизации вещей, и программа становится экспоненциально медленнее, чем ближе вы приближаетесь к пределу.
Кроме того, возможно, вы каждый раз забываете закрывать некоторые объекты, например книгу.
Когда вашему приложению не хватает места в куче, сборщику мусора требуется все больше и больше времени, пытаясь освободить пространство, прежде чем в конечном итоге сдаться и выбросить OutOfMemoryError. Я рекомендую сделать следующее:
добавить параметр JVM -XX: + UseGCOverheadLimit
, чтобы вызвать сбой JVM раньше, когда ей не хватает памяти.
используйте профилировщик памяти для поиска возможных утечек памяти
, если вы не можете найти никаких утечек, просто увеличьте размер кучи.
Если вы по-прежнему получаете эффекты замедления с большей кучей, возможно, проблема связана с используемыми алгоритмами. В этом случае вам нужно использовать профилировщик выполнения, чтобы выяснить, где ваше приложение тратит большую часть своего времени.
[Теория: если ваш addAnswerRow
вызывается повторно, проблема может быть связана с многократным открытием файла электронной таблицы Xcel, размер которого с каждым разом увеличивается. с каждым вызовом addAnswerRow
. Возможно, каждый раз, когда вы открываете файл, он полностью загружается в память.]
Я очень подозреваю, что в вашей программе есть утечка памяти. Используйте профилировщик, например JProfiler или YourKit, для обнаружения утечки памяти. Может быть, вы забыли закрыть WritableWorkbook?
http://jexcelapi.sourceforge.net/resources/javadocs/current/docs/jxl/write/WritableWorkbook.html
Используйте параметр JVM -verbose: gc , чтобы легко проверить, не вызвано ли замедление перегрузкой сборщика мусора.
Увеличение размера кучи может помочь. Можно попробовать установить минимальный и максимальный размер кучи, включив аргументы -Xms и -Xmx. Следующая команда установит минимальный размер кучи как 512 МБ, а максимальную кучу как 1024 МБ.
java -Xms512m -Xmx1024m Моя Программа