Память кучи бесконтрольно растет при создании Excel с помощью SXSSFWorkbook и обработке больших потоков данных.JAVA

Программисты JAVA общаются здесь
Ответить Пред. темаСлед. тема
Anonymous
 Память кучи бесконтрольно растет при создании Excel с помощью SXSSFWorkbook и обработке больших потоков данных.

Сообщение Anonymous »

Я пытаюсь создать файл Excel с помощью Java Stream и SXSSFWorkbook для повышения эффективности использования памяти. Моя цель — обрабатывать большие наборы данных с ограничением размера кучи в 2 ГБ. Однако, несмотря на попытки очистить строки и управлять памятью, использование кучи продолжает расти, пока не исчерпается память. Это мой код:

Код: Выделить всё

@Transactional(readOnly = true)
public byte[] extractInformationAndGenerateExcel(String username, List comuniList) {
logger.info("STARTING EXTRACTION PROCESS FOR: " + comuniList.toString());
try (Stream contrattiEAttrezzatureStream = contrattiAttrezzatureRepository.getReportContrattiAttrezzature(username, comuniList);
ByteArrayOutputStream out = new ByteArrayOutputStream();
Workbook workbook = generateExcelService.generateExcelStream(REPORT_3_CONTRATTI, contrattiEAttrezzatureStream);)
{
workbook.write(out);
if (workbook instanceof SXSSFWorkbook) {
((SXSSFWorkbook) workbook).dispose();
}
return out.toByteArray();
} catch (Exception e) {
throw new RuntimeException(e);
}
}

public  Workbook generateExcelStream(String sheetName, Stream stream) {
logger.info("STARTING WRITING TO FILE: " + sheetName);
final int numberOfRowStoredInMemory = 100;
SXSSFWorkbook wb = new SXSSFWorkbook(numberOfRowStoredInMemory);
wb.setCompressTempFiles(Boolean.TRUE);
SXSSFSheet sheet = (SXSSFSheet) createSheet(sheetName, wb);
sheet.setRandomAccessWindowSize(100);
sheet.createFreezePane(0, 1);

AtomicInteger rowCount = new AtomicInteger(0);

AtomicReference[*]> fields = new AtomicReference(new ArrayList());
List headerNameList = new ArrayList();
Map fieldAlloweds = new HashMap();
Map>();
Map fieldGetterMethods = new HashMap();
stream.forEach(element -> {
if(rowCount.get() == 0) {
Class objectClass = element.getClass();
fields.set(getAllFields(objectClass));
for(Field field : fields.get()){
if (field.isAnnotationPresent(ExcludeFromExcel.class)) {
continue;
}
try {
Class fieldType = field.getType();
fieldTypes.put(field.getName(), fieldType);
fieldAlloweds.put(field.getName(), isFieldTypeAllowed(fieldType));
String headerName = getHeaderColumnName(field);
if(headerName != null){
headerNameList.add(headerName);
}
Method fieldGetterMethod = objectClass.getMethod(getFieldGetterMethodName(field.getName()));
fieldGetterMethods.put(field.getName(), fieldGetterMethod);
} catch (NoSuchMethodException e) {
// Field ignored
}
}
writeHeaderLine(headerNameList, wb, sheet);
}

Row row = sheet.createRow(rowCount.incrementAndGet());
int columnCount = 0;
for (Field field : fields.get()){
if (field.isAnnotationPresent(ExcludeFromExcel.class)) {
continue;
}
Method fieldGetter = fieldGetterMethods.get(field.getName());
if(fieldGetter != null && fieldAlloweds.get(field.getName())){
Object fieldValue = null;
try {
fieldValue = fieldGetter.invoke(element);
} catch (IllegalAccessException | InvocationTargetException e) {
throw new RuntimeException(e);
}
Class  fieldType = fieldTypes.get(field.getName());
if (fieldValue == null) {
fieldValue = "";
fieldType = String.class;
}
createCell(row, columnCount++, fieldValue, fieldType, null);
}
}
if (rowCount.get() % numberOfRowStoredInMemory == 0) {
try {
((SXSSFSheet) sheet).flushRows(numberOfRowStoredInMemory);
} catch (IOException e) {
e.printStackTrace();
}
}
});

return wb;
}

@Query(nativeQuery = true, value = "...My very Long Long query...")
@QueryHints(value = {
@QueryHint(name = "javax.persistence.query.timeout", value = "1200000"),
@QueryHint(name = "org.hibernate.readOnly", value = "true"),
@QueryHint(name = "org.hibernate.fetchSize", value = "50")
})
Stream getReportContrattiAttrezzature(@Param("username") String username, List comuni);
Однако использование памяти продолжает расти. Я использую следующие настройки JVM: -Xmx2g -XX:+UseSerialGC. Как видите, оперативная память ограничена 2ГБ и я не могу ее увеличить. Мой драйвер — jdbc.SQLServerDriver, и я использую SQLServer2019Dialect с Java 1.8
Моя ситуация с использованием VisualVM такова
Изображение

Вот изображение профиля потока моего Java-приложения, показывающее время выполнения и состояние различных потоков во время операции создания отчета Excel:
Изображение
< /p>
Вопросы:

Правильно ли использовать Stream?
[*]Есть ли что-то, что я не учитываю?
[*]Как я могу повысить эффективность использования памяти с помощью моего подхода?
[*]Есть ли лучший вариант способ управления памятью с помощью Apache POI и больших наборов данных при использовании потоков?
Следует ли мне настроить конфигурацию SXSSFWorkbook или существует другая стратегия, которую мне следует рассмотреть, чтобы избежать исчерпания кучи?


Подробнее здесь: https://stackoverflow.com/questions/790 ... ook-and-pr
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «JAVA»