JPA + OutOfMemoryError com jasperreports

25 respostas
furacao123

Estou tentando executar um relatorio de cupons fiscal na minha aplicação, tenho uma classe CupomFiscal que possui uma lista de CupomFiscalItem, passo uma lista de CupomFiscal para o relatorio

JRBeanCollectionDataSource jr = new JRBeanCollectionDataSource(lista);

        Map param = parametros;

        param.put(JRJpaQueryExecuterFactory.PARAMETER_JPA_ENTITY_MANAGER, PersistenceFactory.EM);

        InputStream is = getClass().getResourceAsStream("/relatorio/template/" + relatorio + ".jasper");

        JasperReport report = (JasperReport) JRLoader.loadObject(is);
        JasperPrint print = JasperFillManager.fillReport(report, param, jr);

No momento que eu chamo o fillReport dispara a exception

Exception occurred during event dispatching:
java.lang.OutOfMemoryError: Java heap space
	at java.awt.image.DataBufferInt.<init>(DataBufferInt.java:41)
	at java.awt.image.Raster.createPackedRaster(Raster.java:458)
	at java.awt.image.DirectColorModel.createCompatibleWritableRaster(DirectColorModel.java:1015)

a lista esta indo com 16000 objetos, todos ja foram preinicializados pelo fetch no select, entao gero um unico select para popular a lista de itens de cada cupom, aumentei a memoria para 128 megas mesmo assim disparou a exception mas chegou a abrir o relatorio com 736 paginas, bem lento mas ate abriu.

no subrelatorio eu passo a lista de cupomfiscalitem da seguinte maneira
new net.sf.jasperreports.engine.data.JRBeanCollectionDataSource($F{cupomFiscalItemList})
só navego entre esses 2 objetos CupomFiscal e CupomFiscalItem, quando mando gerar o relatorio fica alguns minutos processando ate disparar a exception, o que pode estar ocorrendo no jasper para dar esse erro?

25 Respostas

nel

Oi!

Tenta jogar 256MB no seu Heap.
E o que pode estar ocorrendo, é o fato do tamanho do Array de bytes que está sendo gerado para construir seu relatório.
Provavelmente está superando o limite de sua JVM e ocorrendo erro.

Se persistir, recomendo gerar os relatórios por partes. Quebra a lista e vai gerando ao invés de enviar os 16 mil objetos de uma única vez.

A

cara,

se vc ja ta passando para o seu relatorio uma lista, vc nao precisa disso aqui nao.

param.put(JRJpaQueryExecuterFactory.PARAMETER_JPA_ENTITY_MANAGER, PersistenceFactory.EM);

t+

furacao123

Mas por se tratar de objetos vindos do JPA eu nao preciso passar o EM?

o que o Jasper faz com a lista de objetos que eu passo, para aumentar tanto assim o tamanho e derrubar toda memoria do java?

nel

furacao123:
Mas por se tratar de objetos vindos do JPA eu nao preciso passar o EM?

o que o Jasper faz com a lista de objetos que eu passo, para aumentar tanto assim o tamanho e derrubar toda memoria do java?

Não, você não precisa. Isso precisaria se quisesse que ele conectasse ao banco para realizar a função de preenchimento, mas isso você já fez.
Então basta indicar a ele que vai receber simplesmente uma lista e mais nada :slight_smile:

Sobre o que o Jasper faz, não tenho conhecimento profundo na API. Provavelmente ele trabalha com array de bytes e isso pode gerar exatamente isso.
Um objeto pode ocuprar menos de 1 kb mas um relatório desse objeto pode ocupar alguns, tu entende ? :slight_smile:

A

cara,

se vc ja ta passando essa lista de objetos para o ireport, vc nao precisa desse parametro.

t+

furacao123

ta entao quando tenho um relatorio muito grande, tenho sempre que quebrar em partes a minha lista, e ir gerando por partes?

A

cara tenta aumentar sua memoria na hora de subir sua aplicação.

t+

furacao123

Entao é uma aplicação desktop com JPA, não queria deixar a aplicação rodando com muita memória para nao sobrecarregar as maquinas, ja coloquei 128m o relatorio ate chegou a abrir mas leva muito tempo para processar e mostrar o relatorio

A

entao cara,

o problema que sao bastante registros.

t+

nel

Então seu problema está resolvido. Pode demorar, mas abre. Fora isso seria utilizar de melhor hardware para o processamento, tens que pensar que o Jasper pega mais de 16 mil registros (objetos), renderiza isso em um layout e gera os respectivos relatórios. Isso é algo que leva tempo e exige hardware mesmo.

Veja os jogos de PC novos, são excelentes, muito dinamicos, com IA de alto nível e etc, mas veja o Hardware que eles exigem.
Por melhor que seja o software ele tem suas limitações e passa a exigir um hardware tão bom quanto , entende ? :slight_smile:

Abraços.

FernandoFranzini

Aplicação java esta precisando gastar mais memoria do que a alocada para JVM. Ou seja, vc ta gerando um numero de objetos que não cabe na memoria alocada.
Como resolver?
- Aumentar memoria da JVM - não resolve, apenas remedia uma vez que o numero de RAM da JVM é fixo, caso a aplicação por ventura suba mais registro, ja era, um abraço com OutOfMemoryError !

  • Diminuir o gasto com objetos - eu vi q vc ta usando JPA passando entidades para o Jasper. Usar JDBC com CacheRowSet fica bem mais rapido e menos custoso.
  • Diminua o gasto com jasper - relatórios grandes no jasper podem gastar um buffer no disco ao inves do HEAP. Veja - http://fernandofranzini.wordpress.com/2010/07/07/outofmemoryireport/
    Veja ai oq vc pode fazer
    T+
nel

FernandoFranzini:
Aplicação java esta precisando gastar mais memoria do que a alocada para JVM. Ou seja, vc ta gerando um numero de objetos que não cabe na memoria alocada.
Como resolver?
- Aumentar memoria da JVM - não resolve, apenas remedia uma vez que o numero de RAM da JVM é fixo, caso a aplicação por ventura suba mais registro, ja era, uma abraço.

  • Diminuir o gasto com objetos - eu vi q vc ta usando JPA passando entidades para o Jasper. Usar JDBC com CacheRowSet fica bem mais rapido e menos custoso.
  • Diminua o gasto com jasper - relatórios grandes no jasper podem gastar um buffer no disco ao inves do HEAP. Veja - http://fernandofranzini.wordpress.com/2010/07/07/outofmemoryireport/
    Veja ai oq vc pode fazer
    T+

Achei bem interessante a opção de virtualização. Eu já trabalher com o Jasper Reports mas como os relatórios não eram tão extensos, nunca tivemos esse problema.
Mas foi bom saber dessa possibilidade.

furacao123

Opa vou dar uma olhada, mas aho que isso resolve o meu problema, valew

furacao123

tentei os 3 metodos, do site mas mesmo assim da o erro de memoria heap, verifiquei o arquivo swap, ele gerou um arquivo de mais de 7 megas.

preciso configurar alguma coisa no ireport no meu relatorio, ou o problema esta no subrelatorio?

leoramos

Cara, com um número de registros tão grande, achas realmente boa ideia não fazer isso direto via SQL? A diferença de desempenho é absurda, e falo por experiência própria.
De qualquer forma… são 16 mil objetos. Mas o que tem em cada um? Eu não acho 16 mil objetos muita coisa, mas claro, depende do conteúdo.
Outra coisa: é comum dar Heap Space com projetos que usam Jasper quando há jars “em excesso”; jars do Jasper que não você não está usando, e por isso sequer precisariam estar no projeto.
Abraço!

FernandoFranzini

furacao123:
tentei os 3 metodos, do site mas mesmo assim da o erro de memoria heap, verifiquei o arquivo swap, ele gerou um arquivo de mais de 7 megas.
preciso configurar alguma coisa no ireport no meu relatorio?

Entenda que que vc ainda ta gastando mais memoria do existe para a JVM
Se o arquivo puro deu 7 mb…quanto mg vc tem de pc??? kkkk é claro q não vai dar…
Vc ta jogando os dados nas entidades JPA certo? Para reduzir o gasto no heap:

  • use JDBC com CachedRowSet.
  • Não de select em dados (colunas) q vc não vai usar…
furacao123

Entao o arquivo chegou nos 7 de megas ate travar o netbeans e disparar o estouro de memoria heap, nao terminou de executar.

qual a melhor maneira de fazer o subrelatorio?

estou passando a lista para o sub da seguinte maneira

new net.sf.jasperreports.engine.data.JRBeanCollectionDataSource($F{cupomFiscalItemList})

mas na hora que monto a lista de cupomFiscal ja dou o fetch para inicializar essa lista de itens, para cada objeto cupom tenho por exemplo em media uns 3 itens, estou fazendo alguma coisa errada na hora de montar o sub?

FernandoFranzini

mas na hora que monto a lista de cupomFiscal ja dou o fetch para inicializar essa lista de itens, para cada objeto cupom tenho por exemplo em media uns 3 itens, estou fazendo alguma coisa errada na hora de montar o sub?

Ta certo…
Quantos registros tem nisso? Quanto de memoria tem sua maquina? Quanto esta alocado para JVM? Projeto é web?

furacao123

esta retornando 6mil registros de cupomfiscal, e em cada cupom tem em media 3 regsitros entao sao 6mil cupons e 18mil itens

fica 6mil em um relatorio e 18mil no sub

projeto desktop e ja liberei 128m para jvm

FernandoFranzini

furacao123:
esta retornando 6mil registros de cupomfiscal, e em cada cupom tem em media 3 regsitros entao sao 6mil cupons e 18mil itens

fica 6mil em um relatorio e 18mil no sub

projeto desktop e ja liberei 128m para jvm

kkkkkkkkkkkkkk
sem chance…oque um ser humano vai fazer com isso?

furacao123

é realmente inviavel mas com a virtualização nao deveria funcionar?

FernandoFranzini

Inviável e impraticável !!! O usuário da uma solução normalmente vai precisar de uma fatia pequena “analitica” ou para grandes informações ficaria “sintético”.
128M para JVM não é nem suficiente para rodar uma aplicação media para SWING!!! sem chance…kkkkk

Se a memoria disponível for dinâmica sim…mas com 100 usuários fazendo essa operação…ja era…

Não se faz coisas do tipo…
Veja praticas aqui documentada por mim q tb podem ser aplicadas ao desktop - http://fernandofranzini.wordpress.com/2009/12/16/praticas-de-aplicativos-web/

furacao123

apliquei com o gzip e aumentei a memoria da jvm para 128m consegui gerar o relatorio, ja com swap e fil acontece o estouro de memoria, vou deixar com gzip e limitar relatorio para 1mes

FernandoFranzini

gzip?
128m é pouco meu…maquinas de supermercado vem com 2GB, da para dar mais sim…

MateusBuck

Porque vc não informa o intervalo máximo e mínimo de memória?

Criado 9 de novembro de 2011
Ultima resposta 10 de nov. de 2011
Respostas 25
Participantes 6