Estouro na memoria

Ola! Estou com um problema muito chato no meu sistema (JAVA SE usando o netbeans, postgres e toplink)sendo que tenho alguma tabelas na base que passam de 5000 registros e no sistema busco ela atraves de uma jtable vinculada a uma list que por sua vez esta vinculada a uma query ligada a um entitymanager. Tenho uma tela de busca de cidades e quando mando abrir a primeira vez esta jtable abre blza, mas na segunda em diante a janela nao abre mais e nao trava apenas clico no botao para abrir a tabela e nao acontece nada! Não sei o que ta ocasionando isto, imagino que sejam os objetos que não estão sendo coletados no garbage collector. Coloquei um codigo ao fechar a janela tipo
cidadeList.removeAll(cidadeList);
cidadeList.clear();
System.gc();
mas nao adiantou! Se alguem puder ajudar agradeço!

Olá amigo,

Pode ser que vc esteja estourando a memória sim

Verifique nos mapeamentos do topLink se vc está trazendo muitos objetos associados dentro da sua lista…

poste aqui o seu mapeamento dos objetos dessa lista para vermos o que occore

Fallow

<?xml version="1.0" encoding="UTF-8"?> <persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"> <persistence-unit name="dbrecepPU" transaction-type="RESOURCE_LOCAL"> <provider>oracle.toplink.essentials.PersistenceProvider</provider> <class>Bean.Cid</class> <class>Bean.Cidade</class> <class>Bean.Convenio</class> <class>Bean.Convpac</class> <class>Bean.Criafichainter</class> <class>Bean.Endmed</class> <class>Bean.Endpac</class> <class>Bean.Endresp</class> <class>Bean.EspMed</class> <class>Bean.Especialidade</class> <class>Bean.InteraltMed</class> <class>Bean.Interalta</class> <class>Bean.Leito</class> <class>Bean.Medico</class> <class>Bean.Paciente</class> <class>Bean.Quarto</class> <class>Bean.RespPac</class> <class>Bean.Responsavel</class> <properties> <property name="toplink.jdbc.user" value="postgres"/> <property name="toplink.jdbc.password" value="****"/> <property name="toplink.jdbc.url" value="jdbc:postgresql://localhost:5432/dbrecep"/> <property name="toplink.jdbc.driver" value="org.postgresql.Driver"/> </properties> </persistence-unit> </persistence>
Esse é o mapeamento da unidade de persistencia

public class Cidade implements Serializable {
    @Transient
    private PropertyChangeSupport changeSupport = new PropertyChangeSupport(this);
    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    @Column(name = "codcidade")
    private Long codcidade;
    @Basic(optional = false)
    @Column(name = "nomecid")
    private String nomecid;
    @Basic(optional = false)
    @Column(name = "ufcid")
    private String ufcid;
    @OneToMany(cascade = CascadeType.MERGE, mappedBy = "codcidade2")
    private List<Endmed> endmedList;
    @OneToMany(cascade = CascadeType.MERGE, mappedBy = "codcidade3")
    private List<Endresp> endrespList;
    @OneToMany(cascade = CascadeType.MERGE, mappedBy = "codcidade4")
    private List<Endpac> endpacList;
    @OneToMany(cascade = CascadeType.MERGE, mappedBy = "codcidade1")
    private List<Paciente> pacienteList;

Este é o do meu Bean que ta dando pau!

Oi shaman,

altere esse trecho de código:

@OneToMany(cascade = CascadeType.MERGE, mappedBy = "codcidade2")
private List&lt;Endmed&gt; endmedList;
@OneToMany(cascade = CascadeType.MERGE, mappedBy = "codcidade3")
private List&lt;Endresp&gt; endrespList;
@OneToMany(cascade = CascadeType.MERGE, mappedBy = "codcidade4")
private List&lt;Endpac&gt; endpacList;
@OneToMany(cascade = CascadeType.MERGE, mappedBy = "codcidade1")
private List&lt;Paciente&gt; pacienteList;

para este:

@OneToMany(cascade = CascadeType.MERGE, mappedBy = "codcidade2", fetch=FetchType.LAZY)
private List&lt;Endmed&gt; endmedList;
@OneToMany(cascade = CascadeType.MERGE, mappedBy = "codcidade3",fetch=FetchType.LAZY)
private List&lt;Endresp&gt; endrespList;
@OneToMany(cascade = CascadeType.MERGE, mappedBy = "codcidade4",fetch=FetchType.LAZY)
private List&lt;Endpac&gt; endpacList;
@OneToMany(cascade = CascadeType.MERGE, mappedBy = "codcidade1",fetch=FetchType.LAZY)
private List&lt;Paciente&gt; pacienteList;

Mude os objetos relacionados para lazy onde somente no momento em que vc estiver dando um “get” o tolink traga esse elemento.

Imagine uma lista de 5000 elementos com cada elemento tendo mais 5 elementos pendurados e mais n elementos pendurados…

Vai estourar mesmo…

PEnsa na possibilidade de vc criar um decorator para esse caso em especifico onde vc vai popular o decorator somente com os atributos convenietes do objeto. Sendo assim vc retornaria uma lista de ObjetoDecorator contendo os atributos que serao listados no jtable. Diminuindo o tamanho da sua lista e de objetos pendurados.

Esperimente o Lazy, caso nao de certo so mesmo com um Objeto decorator.

Espero ter ajudado.
Fallow

Coloquei o fetch mas não melhorou, então o recurso é o decorator, mas minha duvida é o seguinte… Ao popular minha list serei obrigado a usar a pesquisa em cima do bean originario (cidade) para popular o decorador, sendo assim, todos os outros objetos vinculados ao bean cidade tbm irão para memória. Isso nao vai da pau do mesmo jeito? Não sei se era essa tua idéia!?

Ola amigo,

O que vc vai fazer no decorator é criar somente os atributos do seu JTable. Ex.> id, nome,etc…do ti po String;;
No seu decorator vc tb devera ter os getters e setters desses atributos.

Na sua lista que veio da sua consulta na base ao invés de vc dar um return dela no método vc vai iterar essa lista

List&lt;MyDecorator&gt;getUsuarios(){
... \\ fez o select e obteve a lista da base de dados
\\retira dos atributos da lista somnte os atributos que vc quer no JTable eliminando a carga de registros pendurados no JPA

\\far um for para popular uma lista de Decorators com os atributos do JTable
List&lt;MyDecorator&gt; listaToReturn=new ArrayList&lt;MyDecorator&gt;();
for(Usuario usuario:listadeUsuarios){
    MyDecorator myDecorator=new MyDecorator(); 
   myDecorator.setId(usuario.getId());
   myDecorator.setNome(usuario.getNome());
   \\ seta os atributos que vc quer no JTable

   \\ adiciona na lista de Decorators
   listaToReturn.add(myDecorator); \\ adiciona o decorator criado e vai para o proximo registro que veio na lista de usuarios da base

}

return listaToReturn; \\ retorna a lista de decorators sem os atributos da classe usuarios mapeados do hipernate atrelados...
 
}

Espero ter ajudado…
Fallow

Bah cara primeiramente brigadão pela mão que tu ta me dando, mas fiz aquela para que tu indicou e nao parou o estouro ainda, veja o codigo:

[code]public List getCidadeQuery() {

    EntityManager HCBSRecPUEntityManager = java.beans.Beans.isDesignTime() ? null : javax.persistence.Persistence.createEntityManagerFactory("dbrecepPU").createEntityManager();

    Query cidadeQuery = java.beans.Beans.isDesignTime() ? null : HCBSRecPUEntityManager.createQuery("SELECT c FROM Cidade c");
    List<Cidade> ci = cidadeQuery.getResultList();

    List<DecoratorCidade> c = new ArrayList<DecoratorCidade>();
    for(Cidade cid:ci){
        DecoratorCidade dc= new DecoratorCidade();
        dc.setCodcidade(cid.getCodcidade());
        dc.setNomecid(cid.getNomecid());
        dc.setUfcid(cid.getUfcid());

        c.add(dc);

    }
    cidadeQuery = null;
    ci = null;
    HCBSRecPUEntityManager.clear();
    HCBSRecPUEntityManager.close();
    HCBSRecPUEntityManager = null;

    System.gc();

    return c;
}[/code]

Bah ta bucha o negocio! Tem alguma outra ideia de pq nao fumegar?

O decorator parece estar correto,

me manda a classe onde vc chama o método para carregar o JTable, com o evento do botão e se tiver a classe controladora que acessa seu DAO que retorna a lista, pode ser algo na chamada da lista…

Gera um zip das classes somente, do JFRame ou InternalFrame que vc esta usando e a classe controladora.

Usa o Attachments e adiciona aqui no post.

Fico no aguardo.

Conforme tu solitou to mandando os arquivos Blza!?
Explicação:
Cidade => Bean
DecoratorCidade = o proprio nome ja diz
PacEndEditView => Linha 385 onde o metodo chama a janela com a lista, depende
do pc, trava na segunda vez que chama o método, outro na 3 e ai vai
depende da maquina (no cliente é um c2d 2gb RAM , HD 320GB, a placa mae que deixa muito a dezejar
a minha é o mesmo so que uma MB asus e aqui nao trava, testei em outras maquinas com
configuração inferior e tbm trava depois da(s) primeira(s) chamada do metodo busca cidade)

OK Vou verificar agora atarde e te reorno.
Fique tranquilo, pode ser na instanciação ou na chamda do método…

Logo te retorno.
Fallow

Olá shaman_h,

Acabei de Verificar seu código e ja fiz algumas modificações,
no arquivo explicação.txt tem a resposta das modificações.

Fique atento as mudanças, pois ciei uma Classe GenericDAO e Uma Classe CidadeDAO para exemplificar o padrao DAO.
Pesquise sobre Design Patterns.

Também efetuei ajustes na chamada dos forms com o padrao singleton.

Teste as modificações.
Estou a disposição e fico no aguardo.
Fallow

Não fique chutando. Use um profiler:
https://visualvm.dev.java.net/

E lembrem-se também que o padrão Singleton não funciona direito em Java.
Sem falar que variáveis estáticas são uma grande fonte de memory leaks.

Valew Paulo, voce é o cara, pelo conhecimento mas mais ainda pela vontade de ajudar, valew mesmo cara. Eu trabalhava com singleton, com outras bases trabalhava com banco de objetos e o instanciava em objectcontainer que me obrigava a usar o singleton, mas devido a ensinamentos errados (me colocaram no mato) resolvi aplicar em producao e deixei de lado a qualidade. Fica um aviso aos demais, TEM CURSOS DE EMPRESAS NA INTERNET QUE QUEREM QUE VC SE FERRE, não vou citar nomes, mas cuidado com cursos em dvds e tals… Mais uma vez obrigado Paulo, Deus te abençoe!

Resolução (Méritos totais do Paulo)> A forma de produção do netbeans via componentes visuais automatizados gera este estouro, pois a criação de EntityManager e Lists e Queryes automaticas acabam matando a jvm! O negocio é popular tabelas no braço e usar o singleton para conexoes e telas!

O Singleton esconde o real problema, que é não liberar corretamente os recursos de tela. Como você reduziu o número de telas abertas, o problema não fica crítico ao ponto de estourar a VM, mas ele pode voltar se o número de telas diferentes em seu sistema aumentar.

Ou seja, ainda existe o bug no seu código.

Eu mesmo, nunca uso Singletons em minhas telas, pois ele gera um código igualmente ruim, e muitas vezes você precisa abrir duas instâncias da mesma tela (e o singleton não deixará você fazer isso). Use um profiler para identificar o problema real e corrigi-lo.

Bom não querendo ser chepero mas ja sendo, como liberara corretamente estes recursos de tela então?

O primeiro passo é descobrir porque o problema ocorre. Geralmente, um recurso não cai fora pq alguém ainda o está referenciando. Os grandes vilões disso costumam a ser variáveis estáticas (ou seja, usar Singleton também significa que sua janela nunca será liberada da memória);

Quem ajuda a descobrir quem está segurando os objetos é o Visual VM, que indiquei ali em cima. Você deve roda-lo junto com sua aplicação, simular o problema, analisar os dados, e procurar quem é que está segurando os objetos vivos.