Ajuda - Memory Leak em consultas Hibernate

5 respostas
R

Fala pessoal blz?

Estou desesperado atrás de ajuda, pois na finalização da minha aplicação identifiquei um memory leak e não consigo resolvê-lo…
Vamos Lá… Utilizo Hibernate com JPA, e para servidor de aplicações o tomcat 6.0… As minhas consultas são feitas da seguinte forma:

public Collection<Object> carregarDados() {
		logger.debug("** Carregar Indicadores Chamada...");

		EntityManagerFactory entityManagerFactory = Persistence
				.createEntityManagerFactory(PERSISTENCE_UNIT);

		EntityManager em = entityManagerFactory.createEntityManager();
		
		StringBuffer queryString = new StringBuffer(" Select ind FROM Indicador ind  ");		
	
		Query findAllQuery = em.createQuery(queryString.toString());
				
		Collection<Object> indicadores = findAllQuery.getResultList();
		if (indicadores != null){
			logger.debug("** Found " + indicadores.size() + " records:");
		}
		return indicadores;
	}

Então assim, eu compilo a aplicação ela roda numa boa, mas depois de um certo tempo, ela estoura o heap space com:

Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
	at java.util.Arrays.copyOf(Unknown Source)
	at java.lang.AbstractStringBuilder.expandCapacity(Unknown Source)
	at java.lang.AbstractStringBuilder.append(Unknown Source)
	at java.lang.StringBuffer.append(Unknown Source)
	at org.hibernate.sql.SelectFragment.toFragmentString(SelectFragment.java:133)
	at org.hibernate.persister.entity.AbstractEntityPersister.concretePropertySelectFragment(AbstractEntityPersister.java:1191)
	at org.hibernate.persister.entity.AbstractEntityPersister.concretePropertySelectFragment(AbstractEntityPersister.java:1163)
	at org.hibernate.persister.entity.AbstractEntityPersister.generateSnapshotSelectString(AbstractEntityPersister.java:1205)
	at org.hibernate.persister.entity.AbstractEntityPersister.postConstruct(AbstractEntityPersister.java:2979)
	at org.hibernate.persister.entity.SingleTableEntityPersister.<init>(SingleTableEntityPersister.java:431)
	at org.hibernate.persister.PersisterFactory.createClassPersister(PersisterFactory.java:84)
	at org.hibernate.impl.SessionFactoryImpl.<init>(SessionFactoryImpl.java:261)
	at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1327)
	at org.hibernate.cfg.AnnotationConfiguration.buildSessionFactory(AnnotationConfiguration.java:867)
	at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:669)
	at org.hibernate.ejb.HibernatePersistence.createEntityManagerFactory(HibernatePersistence.java:126)
	at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:52)
	at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:34)
	at com.Syge.database.ServIndicadores.carregarDados(ServIndicadores.java:302)
	at principal.main.main(main.java:41)

Ja aumentei a memória da JVM, mas isso só prolonga o erro, o problema é como se a memoria fosse crescendo gradativamente e o Garbage Collector nunca coletasse os objetos inativos… Estou fazendo alguma coisa errado nas minhas consultas? Preciso de ajuda urgente, pois nem todo cliente tem condições de utilizar JVM com grande capacidade de memória… Preciso saber o que está causando esse memory leak, e o q esta consumindo a memória e não esta sendo removido do HEAP com o Garbage Collector

Desde Ja Agradeço
Att

5 Respostas

R

Objeto que esta sendo buscado

//Código auto incremento do indicador. É a chave primaria
	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	@Column(name = "IND_SEQ", nullable = false)
	private	int codigoIndicador; //IND_SEQ
	
	//Nome do indicador. Campo obrigatorio. Responsável por identificar o indicador.
	@Basic
	@Column(name = "IND_DSC_NOME", nullable = false, unique = false)
	private	String nomeIndicador;
	
	//Indentifica se o indicador é ou não acumulado. Deverá ser preenchido  com os valores: acumulado/não acumulado
	@Basic
	@Column(name = "IND_FLG_TIPO", nullable=false)
	private String flagTipo;
	
	//Relaciona com a tabela: UNIDADE_MEDIDA -Identifica a unidade de medida do indicador.

	@ManyToOne
	@JoinColumn(name="UND_DSC_SIGLA")
	private UnidadeDeMedida unidadeDeMedida;
	
	//Relaciona com a tabela: PERIODICIDADE - Identifica qual o tipo de periodicidade daquele indicador.
	@ManyToOne
	@JoinColumn(name="PED_SEQ")
	private Periodicidade periodicidade;
	
	//Relaciona com a tabela: POLARIDADE - Identifica a polaridade do indicador
	@ManyToOne
	@JoinColumn(name="POL_SEQ")
	public Polaridade polaridade;
	
	//Relaciona com a tabela: FAROL-Identifica o tipo de farol daquele indicador. É a base de como será calculado os farol do indicador.
	@ManyToOne
	@JoinColumn(name="FAR_SEQ")
	private Farol farol;
	
	//Relaciona com a tabela: ORGANIZACAO - Define de qual organização/empresa o indicador pertence. Pois no sistema  podemos administrar mais de uma empresa.
	@ManyToOne
	@JoinColumn(name="ORG_SEQ")
	private Organizacao organizacao;
	
	//Relaciona com a tabela: UNIDADE_ORGANIZACIONAL - Define de qual unidade organizacional pertece aquele indicador. Deve ser de uma unidade organizacional da Organização escolhida.
	@ManyToOne
	@JoinColumn(name="UNO_SEQ")
	private UnidadeOrganizacional unidadeOrganizacional;

	//Relaciona com a tabela: COMITE_ORGANIZACAO - Define se o indicador pertence a um comite de uma organização. Deverá ser de um comite da organização escolhida.
	/*
	@ManyToOne
	@JoinColumn(name="COM_SEQ")
	private Comite comite;
	*/
	@Basic
	@Column(name="COM_SEQ",nullable=true)
	private String idComite;
	
	//Relaciona com a tabela: OBJETIVO - Define qual o objetivo pai daquele indicador.
	@ManyToOne
	@JoinColumn(name="OBJ_SEQ")
	private Objetivo objetivo;

	
	//Relaciona com a tabela: PESSOA - Define o responsavel pelo indicador.
	@ManyToOne
	@JoinColumn(name="PES_SEQ")
	private Pessoa pessoa;

	
	//Define se o indicador pai daquele indicador. - Relaciona-se consigo mesma
	@ManyToOne
	@JoinColumn(name="IND_IND_SEQ",referencedColumnName="IND_SEQ")
	private Indicador indicador; 

	@Basic
	@Column (name="IND_DAT_VALID")
	private Date dataValidade;
	
	//Define se o indicador tem lançamento de valor de alarme. 
	//Caso S o lançamento do alarme será obrigatorio no preenchimento do valor. Valore: ?S?/?N?
	@Basic
	@Column(name="IND_ALARMES",nullable=false)
	private int flagAlarme;
	
	//Define se o indicador é um indicador ativo ou inativo. Valores ?i?/?a?
	@Basic
	@Column(name="IND_FLG_STATU")
	private char flagAtivo;
	
	//Campo texto para preenchimento de observação.
	@Basic
	@Column(name="IND_TXT_INDIC")
	private String observacaoIndicador;
	
	//Campo texto onde sera gravado a formula do indicador. Campo é preenchido automatico pela tela de formula.
	@Basic
	@Column(name="IND_DSC_FORMU")
	private String formulaIndicador;
	
	//Campo texto onde sera gravado a formula do acumulado. Campo preenchido automatico pela tela de formula.
	@Basic
	@Column(name="IND_DSC_FORMU_ACUMU")
	private String formulaAcumulado;
J

Isso pode ser um bug no proprio hibernate. Procure saber quantos registros sua consulta está retornando. Pega os fontes do hibernate e depura ele.

R

Teria como você ser mais específico? Pelo q eu olhei na internet eu vi vários problemas com relação a memory leaks… mas nenhum deles se aplicaram ao meu caso

LeoMarola

Realizando a mesma consulta no banco , quanto tempo demora ? qual a quantidade aproximada (ordem) dos registros ?

Um fator importante e usar “Lazy” nas suas associacoes, sempre que possivel.

Se vc acessar: http://www.oracle.com/technology/products/ias/toplink/jpa/resources/toplink-jpa-annotations.html#ManyToOne

Verá que o default é “eager”, logo, vc estará buscando informacoes de varias tabelas, o que pode está te onerando. Ve se ajuda essas dicas.

:wink:

Mordor

Estou com o mesmo problema.
Fiz um teste e cada vez que executo a consulta a memoria aumenta até estourar a memoria.
Alguem conseguiu resolver este problema?

Criado 10 de março de 2009
Ultima resposta 14 de mai. de 2009
Respostas 5
Participantes 4