Método dispose não encontrado no SXSSF

Pessoal,

Estou tentando criar um arquivo arquivo xlsx. Consegui com sucesso utilizando a API XSSF do POI.
Entretando, ao tentar gerar arquivos com mais de 15 mil linhas, a memória não é o suficiente e é gerado o erro java.lang.OutOfMemoryError: GC overhead limit exceeded . O que imagino que aconteça é que todos os dados são gravados na memória e só no final do processamento é que eles são jogados no arquivo destino.

Vi que para arquivos grandes, há a API SXSSF, também do POI, onde podemos definir quantos registros ficam na memória e, ao atingir o número definido, eles são gravados no arquivo.
O problema é que na página da SXSSF ele manda utilizar o método dispose, o qual a IDE diz não encontrar.

Citação na página da SXSSF:
Note that SXSSF allocates temporary files that you must always clean up explicitly, by calling the dispose method.

Eu importei todos os arquivos jar disponíveis do POI e não sei o que pode ser, já que o método dispose é mencionado na documentação.

Pessoal,

Descobri o problema.
É necessária a biblioteca commons compress (não disponível no site do POI), e a que me passaram era de uma versão antiga. Baixei a versão 1.18 e o erro foi solucionado.

java.lang.OutOfMemoryError: GC overhead limit exceeded acontece quando a máquina virtual fica mais de 98% do tempo trabalhando e liberando menos de 2% de memória.

Posta o seu código, alguma coisa não está bem implementada.

Staroski, creio que esse erro seja comum na utilização da XSSF.
Estou implementando o código dentro do Informatica PowerCenter, que é uma ferramenta ETL. Vou disponibilizar apenas os métodos que utilizo e como são chamados, pois o código completo que a ferramenta gera é muito grande e atrapalharia a leitura, pois contem informações que são utilizadas apenas pela ferramenta ETL. Caso mesmo assim deseje visualizar o código completo, eu posto aqui.

  • Imports
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.*;
import org.apache.poi.xssf.streaming.*;

import java.io.File;
import java.io.FileOutputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
  • Variáveis
private static final String ARQUIVO = “/powercenter/P001/ID/CAMADA_INTEGRACAO_SAP/ENTRADA/PROCESSADO/RELATORIO/LOG_DETALHE.xlsx”;

private static String[] columnsDPContabil = {“DG_EMPRESA”,“DG_ORIGEM”,“DG_TP_MOVIMENTO”,“DG_DT_MOVIMENTO”,“DG_NR_SEQ”,“DG_CHAVE”,“DG_PARCELA”,“DG_MAIN”,“DG_SUB”,“DG_RAMO”,“DG_COSS_RESS”,“DT_CARGA”};

private static int COLUMN_DPC_DG_EMPRESA = 0;
private static int COLUMN_DPC_DG_ORIGEM = 1;
private static int COLUMN_DPC_DG_TP_MOVIMENTO = 2;
private static int COLUMN_DPC_DG_DT_MOVIMENTO = 3;
private static int COLUMN_DPC_DG_NR_SEQ = 4;
private static int COLUMN_DPC_DG_CHAVE = 5;
private static int COLUMN_DPC_DG_PARCELA = 6;
private static int COLUMN_DPC_DG_MAIN = 7;
private static int COLUMN_DPC_DG_SUB = 8;
private static int COLUMN_DPC_DG_RAMO = 9;
private static int COLUMN_DPC_DG_COSS_RESS = 10;
private static int COLUMN_DPC_DT_CARGA = 11;

private static int countDPContabil = 0;

private static boolean called = false;
private static Date DT_CARGA;

private static Workbook workbook;
private static Sheet sheetLogDetalhe;
private static Sheet sheetDPContabil;
private static CellStyle dateCellStyle;
private static CreationHelper createHelper;
  • Métodos

A ferramenta pega os dados do banco e passa para a transformação Java, onde implemento esse código.
Então, as variáveis que possuem o prefixo “DPC_DG_” contem os dados do select do banco. Essas variáveis já são definidas automaticamente pela ferramenta e estão disponíveis no código completo. Por isso não preciso fazer nada além de utilizá-las, como neste exemplo:

cellDPC_DG_EMPRESA.setCellValue(DPC_DG_EMPRESA);

Só consigo chamar os métodos a cada registro lido (resultado do select do banco).
Chamo apenas os métodos createTemplate() e writeRowDPContabil().
Resumindo, para cada registro que leio, chamo os dois métodos acima.

EDIT: acabei postando com a utilização do SXSSF. Atualizei para o XSSF, que é o que retorna OutOfMemoryError.

public void createTemplate()

{
    if (called) return;
	called = true;
	
	// Create a Workbook 
	workbook = new XSSFWorkbook();

	createCellStyleDPContabil();
		
	// Create sheet
	sheetDPContabil= workbook.createSheet("DE_PARA_CONTABIL");

	// Create header
	createHeaderDPContabil();

	DT_CARGA = getDTCarga();

}

public void createHeaderDPContabil()
{
	// Create a Row for the header
	Row headerRowDPContabil = sheetDPContabil.createRow(0);

	for(int i = 0; i < columnsDPContabil.length; i++) {
		Cell cell = headerRowDPContabil.createCell(i);
		cell.setCellValue(columnsDPContabil[i]);
		//cell.setCellStyle(headerCellStyle);
       }
}

public void writeRowDPContabil()
{
	Row rowDPContabil = sheetDPContabil.createRow(nextRowDPContabil());

	Cell cellDPC_DG_EMPRESA = rowDPContabil.createCell(COLUMN_DPC_DG_EMPRESA);
	Cell cellDPC_DG_ORIGEM = rowDPContabil.createCell(COLUMN_DPC_DG_ORIGEM);
	Cell cellDPC_DG_TP_MOVIMENTO = rowDPContabil.createCell(COLUMN_DPC_DG_TP_MOVIMENTO);
	Cell cellDPC_DG_DT_MOVIMENTO = rowDPContabil.createCell(COLUMN_DPC_DG_DT_MOVIMENTO);
	Cell cellDPC_DG_NR_SEQ = rowDPContabil.createCell(COLUMN_DPC_DG_NR_SEQ);
	Cell cellDPC_DG_CHAVE = rowDPContabil.createCell(COLUMN_DPC_DG_CHAVE);
	Cell cellDPC_DG_PARCELA = rowDPContabil.createCell(COLUMN_DPC_DG_PARCELA);
	Cell cellDPC_DG_MAIN = rowDPContabil.createCell(COLUMN_DPC_DG_MAIN);
	Cell cellDPC_DG_SUB = rowDPContabil.createCell(COLUMN_DPC_DG_SUB);
	Cell cellDPC_DG_RAMO = rowDPContabil.createCell(COLUMN_DPC_DG_RAMO);
	Cell cellDPC_DG_COSS_RESS = rowDPContabil.createCell(COLUMN_DPC_DG_COSS_RESS);
	Cell cellDPC_DT_CARGA = rowDPContabil.createCell(COLUMN_DPC_DT_CARGA);

	cellDPC_DG_EMPRESA.setCellValue(DPC_DG_EMPRESA);
	cellDPC_DG_ORIGEM.setCellValue(DPC_DG_ORIGEM);
	cellDPC_DG_TP_MOVIMENTO.setCellValue(DPC_DG_TP_MOVIMENTO);
	cellDPC_DG_DT_MOVIMENTO.setCellValue(DPC_DG_DT_MOVIMENTO);
	cellDPC_DG_NR_SEQ.setCellValue(DPC_DG_NR_SEQ);
	cellDPC_DG_CHAVE.setCellValue(DPC_DG_CHAVE);
	cellDPC_DG_PARCELA.setCellValue(DPC_DG_PARCELA);
	cellDPC_DG_MAIN.setCellValue(DPC_DG_MAIN);
	cellDPC_DG_SUB.setCellValue(DPC_DG_SUB);
	cellDPC_DG_RAMO.setCellValue(DPC_DG_RAMO);
	cellDPC_DG_COSS_RESS.setCellValue(DPC_DG_COSS_RESS);
	cellDPC_DT_CARGA.setCellValue(DT_CARGA);

	cellDPC_DT_CARGA.setCellStyle(dateCellStyle);
}

public int nextRowDPContabil()
{
	return ++countDPContabil;
}

public void createCellStyleDPContabil()
{

	// CreationHelper helps us create instances of various things like DataFormat, 
	// Hyperlink, RichTextString etc, in a format (HSSF, XSSF) independent way
	createHelper = workbook.getCreationHelper();

	// Create Cell Style for formatting Date
	dateCellStyle = workbook.createCellStyle();
	dateCellStyle.setDataFormat(createHelper.createDataFormat().getFormat("dd-MM-yyyy"));
}

public Date getDTCarga()
{
	Date date = new Date();
	return date;
}

public void closeFile()
{
	try {
		FileOutputStream fos = new FileOutputStream(new File(ARQUIVO));
		workbook.write(fos);
		fos.close();
		// dispose of temporary files backing this workbook on disk
        	workbook.dispose();

		System.out.println("Criacao do XSLX terminada com sucesso!");
	} catch (FileNotFoundException ex) {
		ex.printStackTrace();
	} catch (IOException ex) {
		ex.printStackTrace();
	}
 
}