Melhor forma de instanciar as telas e manipula-las

Bom dia a todos, sei que é uma pergunta talvez boba, mas estou no meu primeiro projeto e estou terminando algumas telas e preciso começar os testes colocando o sistema pra “trabalhar” de verdade, a minha dúvida é a seguinte, qual a melhor forma de instanciar uma tela, sendo um JFrame, JDialog ou qualquer outro modelo??

A minha dúvida surgiu pela seguinte questão, se eu criar um novo objeto a cada vez que precisar de uma tela, a memória da máquina não vai encher? ou quando eu dou um dispose() destrói o objeto que foi instaciado em memória?

por exemplo, aprendi desta forma na faculdade:

TelaDesejada telaDesejada = new TelaDesejada(null); telaDesejada.setModal(true); telaDesejada.setVisible(true);

esta bem simples só pra exemplo, o que eu quero saber é se estanciar o frame assim, quando eu der o dispose() vai destruir o objeto da memória ou ele continuará lá, assim carregando a memória da máquina?

Essa dúvida surgiu pelo fato de que na faculdade tivemos esse problema, deu OverFlow na máquina, ai fomos descobrir que poderia ser pelo fato de cada nova instancia um novo objeto, lotando a memória!

minha dúvida é se realmente existe isso, e qual a melhor forma de solucionar o problema ou mesmo de instancar uma tela e chama-la sempre que preciso sem pesar a máquina!

desde já obrigado a todos pela atenção!!

só uma observação, eu coloquei neste tópico, agora não sei se foi o correto, caso não peço desculpas!!

Bem, teoricamente, uma referência a um objeto que não esteja mais em uso, deverá ser apagada da memória pelo Garbage Collector.

E o dispose deve auxiliar nesse processo.

Outra forma é você seguir a estrutura MVC e criar uma classe de controle e a partir dela, e somente nela, instanciar as tuas telas.

Assim haverá uma única variável, por exemplo, para a tela de CadastroX, e quando você precisar dela você pega a instância da
classe Controle e executa o método que faz aparecer essa classe. Assim, ela mesmo que fique na memória, será apenas um objeto
daquela classe sempre.

Dá um pouco de trabalho, mas tudo tende a ficar mais organizado.

Entendeu? Qualquer coisa fale e faço um protótipo e posto.

Se vc liberar o ponteiro, o objeto estará elegível para ser coletado caso o GC precise liberar memoria, caso contrario vai estorar.

Leia a documentação do método que vc vai descobrir…

Para se escrever uma aplicação Java vc precisa entender 3 coisas:

  1. como funciona a memoria do java e o coletor de lixo GC
    2)praticas de programação
    3)melhor forma de se otimizar o gasto da sua aplicação
    …que é claro não caberia comentar aqui…

Amigo para janelas modais que só pode existir uma única referência eu uso o padrao singleton

segue exemplo

public class ClienteView extends JDialog
{
private static ClienteView			clienteView			= null;

	public static ClienteView getInstance(Frame owner)
	{
		if(clienteView == null)
			clienteView = new ClienteView(owner);
		return clienteView;
	}

	private ClienteView(Frame owner)
	{
		super(owner, true);
	}

	public void dispose()
	{
		clienteView = null;
		super.dispose();
	}
}

E minha chamada fica assim

ClienteView clienteView = ClienteView.getInstance(this);
clienteView.setVisible(true);

Bom eu faço da seguinte forma, como este usuario é um JInternalFrame, eu crio direto a classe e passo a janela, para add a tela de usuario, não sei se é a melhor forma mas funciona muito bem nos meus casos, e mesmo que não vá add eu uso a chamada desta mesma forma

itemUsuarios.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { new Usuarios(janela); } });

:smiley:

e no caso de ocupar muita memória da maquina, eu faça da seguinte forma, criei um meio de bloquear um limite de 5 telas podem ser abertas simultaneamente, e apenas uma tela de cada classe tipo… 1 de usuario, 1 de cliente.

Foi a melhor maneira que encontrei de não deixar carregar muito a máquina, já vi dar muitos problemas com isso no sistema que uso aqui na empresa

Eu só queria ponderar o seguinte:

  1. Cada passada do coletor de lixo GC é sincronizado, ou seja, o sistema para de funcionar enquanto ele esta limpando a memoria. Ou seja denovo, reduz performance.
  2. Um objeto que é esporadicamente usado no workflow da solução, compensa criar ele na hora, usar e deixa-lo elegível para ser removido pelo coletor. E assim vc libera a memoria para a solução.
  3. Um objeto que é usado continuamente no workflow, não compensa ficar criando e destruindo, pq ele pode ser encarretado no HEAP, podendo ter picos de falta de memoria. Para objetos desse tipo no qual o workflow da solução aponta claramente que ele vai ser sempre usado, compensa aplicação do singleton que faz ele ser instanciado apenas 1 vez, lembrando que isso vai gastar memoria continua.

O projetista/programador/responsável tem que entender e mapear e aplicar a melhor solução. Qualquer inversão de aplicatibilidade é prejudicial.

Ola JoaoBluSCBR, então cara, estou fazendo da forma que você comentou, tenho uma classe onde eu instancio todos os frames, e trabalho com o Visible(), ainda ontem a noite estava estruturando todos frames dessa forma, então quando eu chamo qualquer tela derivada do Jframe eu tenho que colocar o seguinte código: frame.main(null),isso faz com que a tela fique normal e funciona tudo correto, só fiquei com dúvida se estava realmente certo por um único motivo: em uma determinada tela, ao dar o dispose, visible(false), ela não desaparece, fica ativa e tenho que mandar parar a execução direto no Eclipse, no console. Já as JDialog funciona normal somente com o visible(false), e mais duas telas Jframe que deu tempo de testar também funcionam perfeitamente usando o dispose. Não sei se posso ter criado essa tela com alguma configuração que esteja em conflito. não da erro algum, somente não fecha, mesmo com dispose().

se você puder postar somente um exemplo simples pra eu ver se estou fazendo de forma correta, tanto a instancia quanto os comandos para ocultar a tela eu agradeço muito. e peço desculpas pela ignorância!! rsrsrs


Ja para o FernandoFranzini, obrigado pelo toque, vou procurar me aprofundar mais nesse parte, é interessante mesmo, se tiver algum link que ensine ou descreva os assuntos eu agradeceria, ja que conhece do assunto sabe me referenciar bons materiais, livros, artigos…

muito obrigado pela atenção de todos!!

http://www.oracle.com/technetwork/java/javase/gc-tuning-6-140523.html

Poxa Fernando, valeu mesmo amigo, agradeço muito sua atenção, ja me esclereceu muita coisa com a dúvida que surgiu, vou fazer dessa forma então, com relação a qual frame instaciar na inicialização do sistema, agradeço mesmo!!

e vou procurar aprender mais sobre o assunto, que pode fazer muita a diferença no final das contas!

[quote=Emerson_sannin]Poxa Fernando, valeu mesmo amigo, agradeço muito sua atenção, ja me esclereceu muita coisa com a dúvida que surgiu, vou fazer dessa forma então, com relação a qual frame instaciar na inicialização do sistema, agradeço mesmo!!
e vou procurar aprender mais sobre o assunto, que pode fazer muita a diferença no final das contas![/quote]
Sim…questões arquiteturais dessa natureza tem grandes variações de projeto para projeto…ou seja…não é indicado adotar a opinião de um ou outro, uma vez que o que foi aplicável para um pode não ser para seu caso. Por isso vc precisa entender do contexto para ter condições de tomar a melhor decisão.
T+

[quote=FernandoFranzini]Eu só queria ponderar o seguinte:

  1. Cada passada do coletor de lixo GC é sincronizado, ou seja, o sistema para de funcionar enquanto ele esta limpando a memoria. Ou seja denovo, reduz performance.
  2. Um objeto que é esporadicamente usado no workflow da solução, compensa criar ele na hora, usar e deixa-lo elegível para ser removido pelo coletor. E assim vc libera a memoria para a solução.
  3. Um objeto que é usado continuamente no workflow, não compensa ficar criando e destruindo, pq ele pode ser encarretado no HEAP, podendo ter picos de falta de memoria. Para objetos desse tipo no qual o workflow da solução aponta claramente que ele vai ser sempre usado, compensa aplicação do singleton que faz ele ser instanciado apenas 1 vez, lembrando que isso vai gastar memoria continua.

O projetista/programador/responsável tem que entender e mapear e aplicar a melhor solução. Qualquer inversão de aplicatibilidade é prejudicial.[/quote]

Apenas um detalhe a discutir sobre o ítem 1: O GC roda em uma thread de menor prioridade possível. Isso significa que ele só vai ser posto para funcionar se o sistema não tiver mais nenhuma thread de prioridade mais elevada funcionando. Isto quer dizer que dificilmente o sistema para fazer a coleta do lixo se houver algo em processamento como janelas em operação. É claro que isso pode colocar em perigo os requisitos de memória e o GC ter de ser promovido para agir rapidamente, mas dificilmente o GC causa perda de performance em uma aplicação normal.

Emerson_sannin

Vou tentar fazer um modelo da minha sugestão e te passo daqui a pouco.

Não é garantido…os documentos dizem que "garbage collection performance is not significant."
De qualquer forma, fica em aberto kkkkk

Eu usaria algo como o código em anexo.

É claro que quando um Dialog é aberto ele é modal e domina até que seja fechado, então não faz
sentido se preocupar com o código de dispose dele. Afinal basta colocar o setDefaultClose certo e
ele sofrerá um dispose. Se quiser garantir jogue null na variavel dele e pronto.

Quanto aos Frames, o processo que está no anexo garante que apenas uma variavel seja
instanciada e usada na memoria, não há o risco de criar um new e mesmo que este seja criado
sobreporá a área de memória reservada para a variavel no new anterior.

Creio que evita o overflow o máximo possível.

Nossa muito legal esse código que você passou, peguei ele aqui vou dar uma estudada, ainda to aprendendo a mexer com a parte de Swing, todo o exemplo que podemos ter é muito util, ainda mais os JTables, que são muito legais de mexer

VLW msm

legal, obrigado, assim que puder, vou testar e posto o resultado aqui pro pessoal, grande abraço! nunca tinha feito desta forma, assim pode istanciar no próprio frame e somente chama quando preciso… hehehe legal.

Ola pessoal, voltei, demorei mas voltei. Agradeço a todos pela ajuda, consegui passar pela fase de erro ao fechar as telas, depois de muuuuuitos testes descobri o problema, acontece o seguinte:

Antes de tudo segui os conselhos e criei duas(pra ficar mais fácil a identificação) classes de controle, ControledeTelas -que controla as chamadas de métodos, setar variáveis, referenciar algo… - e ChamaTelas, que é onde instancio as telas.

Em várias telas eu preciso acessar métodos e as vezes até mesmo instanciar alguma variavel em outra tela, um exemplo é a tela de ConsultaCliente, ela é necessária em algumas telas, como venda e cadastrodeCliente. Preciso setar um variável para determinar qual tela esta invocando a consulta e saber onde vou restaurar, acontece que ao antes eu chamava tudo direto do Frame, por exemplo: ConsultaClienteVIEW.chamadoPorCadCliente = true;, eu utilizava a própria classe, ao invés de fazer ConsultaClienteVIEW consultaClienteVIEW = new ConsultaClienteVIEW(); ConsultaClienteVIEW.chamadoPorCadCliente = true;, mas era necessário deixar as variáveis, funções, ou até mesmo os componentes utilizados dessa forma como static, e automaticamente, todos métodos que os utilizavam, e novamente todos os compomentes dentro desse métodos tbm, assim, proticamente tudo ficava static, sei que provavelmente é errado, mas estou aprendendo, então vou melhorando a cada nova descoberta, mas o problema surgiu agora, onde ao instanciar a tela eu fechava a primeira vez corretamente, mas quando instaciava a segunda vez, não dava dispose();de forma alguma, não fechava.

descobrindo isso através de testes, eu retirei todos os static e joguei tudo isso para a “ControleTela”, assim fica tudo maravilhosamente lindo, até a hora que eu preciso utiliza-las, quando eu tento instanciar alguma variável, chamar algum método ou algo do tipo de outra tela da erro, Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException at CTR.ControleTelasCTR.setaCadastroproduto_consultaProduto(ControleTelasCTR.java:29) at VIEW.ProdutoVIEW$6.actionPerformed(ProdutoVIEW.java:363) at javax.swing.AbstractButton.fireActionPerformed(Unknown Source) at javax.swing.AbstractButton$Handler.actionPerformed(Unknown Source) at javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source) at javax.swing.DefaultButtonModel.setPressed(Unknown Source) at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(Unknown Source) at java.awt.AWTEventMulticaster.mouseReleased(Unknown Source) at java.awt.Component.processMouseEvent(Unknown Source) at javax.swing.JComponent.processMouseEvent(Unknown Source) at java.awt.Component.processEvent(Unknown Source) at java.awt.Container.processEvent(Unknown Source) at java.awt.Component.dispatchEventImpl(Unknown Source) at java.awt.Container.dispatchEventImpl(Unknown Source) at java.awt.Component.dispatchEvent(Unknown Source) at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source) at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source) at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source) at java.awt.Container.dispatchEventImpl(Unknown Source) at java.awt.Window.dispatchEventImpl(Unknown Source) at java.awt.Component.dispatchEvent(Unknown Source) at java.awt.EventQueue.dispatchEventImpl(Unknown Source) at java.awt.EventQueue.access$000(Unknown Source) at java.awt.EventQueue$1.run(Unknown Source) at java.awt.EventQueue$1.run(Unknown Source) at java.security.AccessController.doPrivileged(Native Method) at java.security.AccessControlContext$1.doIntersectionPrivilege(Unknown Source) at java.security.AccessControlContext$1.doIntersectionPrivilege(Unknown Source) at java.awt.EventQueue$2.run(Unknown Source) at java.awt.EventQueue$2.run(Unknown Source) at java.security.AccessController.doPrivileged(Native Method) at java.security.AccessControlContext$1.doIntersectionPrivilege(Unknown Source) at java.awt.EventQueue.dispatchEvent(Unknown Source) at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source) at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source) at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source) at java.awt.EventDispatchThread.pumpEvents(Unknown Source) at java.awt.EventDispatchThread.pumpEvents(Unknown Source) at java.awt.EventDispatchThread.run(Unknown Source)

reference a estas linhas:chamaTelaCTR.consultaClienteVIEW.chamadoporvenda = true;onde “chamadoporvenda” é uma boolean, utilizada para o exemplo dado acima!

outro erro é aqui(mesmo erro): (classe ControleTelas)

public void restauraProduto_Produto(int cod, boolean parametroPorId){ chamaTelaCTR.produtoVIEW.restaurarDados(cod, parametroPorId); } na linha 2.
não sei o que posso estar fazendo errado, ou se esse não é possível fazer assim, se alguém puder me ajudar, ou até demonstrar maneira melhor de fazer essas chamadas agradeço.

ficou da seguinte forma(ex): PodutoVIEW() --> ChamaTelaCTR() --> ConsultaProdutoVIEW() --> ControleTelasCTR() (aciona) --> ProdutoVIEW.restaurarProduto();

em código agora:

...//ProdutoVIEW(). btnLocalizar.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent e) { controleTelasCTR.setaCadastroproduto_consultaProduto(); // aqui eu seto a variavel boolean para saber "quem" chamou a tela ao restaurar. mas o erro ocorre aqui chamaTelaCTR.chamaConsultaProduto(); }

...//ChamaTelaCTR(). public Window ChamaConsultaProduto(){ if(consultaProdutoVIEW == null) consultaProdutoVIEW = new ConsultaProdutoVIEW(null); consultaProdutoVIEW.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); consultaProdutoVIEW.setLocationRelativeTo(null); consultaProdutoVIEW.setResizable(false); consultaProdutoVIEW.setVisible(true); return consultaProdutoVIEW; }

...//ControleTelaCTR(). public void setaCadastroproduto_consultaProduto(){ chamaTelaCTR.consultaProdutoVIEW.cadastroproduto = true; // ocorre erro aqui. chamaTelaCTR.consultaProdutoVIEW.venda = true; }

...//ConsultaProdutoVIEW public void restaurarDados(int cod){ if(cadastroproduto){ controleTelasCTR.restauraProduto_Produto(cod, true); } }

...//ControleTelasCTR public void restauraProduto_Produto(int cod, boolean parametroPorId){ chamaTelaCTR.produtoVIEW.restaurarDados(cod, parametroPorId); // ocorre erro aqui. }

lembrando que em todos o erro é o mesmo que postei acima!

se alguém encontrar um erro, ou feito de forma incirreta agradeço!