Existe uma boa razão para usar o método dispose() para fechar uma janela?
Ou é melhor usar setVisible(false) ?
Sei que dispose() libera alguns recursos, mas ainda é possível reabrir a janela.
Existe uma boa razão para usar o método dispose() para fechar uma janela?
Ou é melhor usar setVisible(false) ?
Sei que dispose() libera alguns recursos, mas ainda é possível reabrir a janela.
É bom utilizar setVisible(true),
e com relação ao dispose, uma serventia é para quanto você ter uma janela principal
onde essa janela pode abrir outras janelas, quando for fechas as outra(s) janela(s) você
utiliza dispose(), porque caso você use System.exit(0), você terminará a execução do
programa, e com dispose não. Entendeu?
É bom utilizar setVisible(true),
e com relação ao dispose, uma serventia é para quanto você ter uma janela principal
onde essa janela pode abrir outras janelas, quando for fechas as outra(s) janela(s) você
utiliza dispose(), porque caso você useSystem.exit(0), você terminará a execução do
programa, e com dispose não. Entendeu?
Sim, isso eu já sabia.
Pelo que entendi, as vantagens de usar dispose() são:
Liberar a memória que a janela está utilizando;
Se fechar todas as janelas usando dispose(), a máquina virtual será encerrada (na maioria das vezes). Se fechar usando setVisible() o programa continuará executando, apesar de nenhuma janela estar visível.
http://java.sun.com/javase/6/docs/api/java/awt/Window.html#dispose()
Isso mesmo, não utilize setVisible(false), a janela estará aberta, mas não visível, e com dispose não
ela fechará e sairá da memória.
Isso mesmo, não utilize setVisible(false), a janela estará aberta, mas não visível, e com dispose não
ela fechará e sairá da memória.
O que o dispose faz é liberar os recursos do sistema operacional relacionados a janela. Mas a memória ocupada pela parte java da janela (textfields, botões, etc) permanece lá.
Funciona assim, quando você abre uma janela, o java solicita ao SO um objeto Window, com um Canvas. E desenha lá os objetos java que você colocou. É esse objeto window, com esse canvas que são liberados no dispose. Caso a janela seja criada novamente, um novo objeto window será solicitado, mas como a parte java (descrição de que botões, labels, etc a janela tem) não foi liberada, ele pode redesenhar tudo.
Para realmente liberar a janela da memória, você deve além de chamar o dispose() fazer como toda variável java: remover as referências a janela.
Mas o Garbage Collector não faz isso?
Não.
Pense no Garbage Collector como uma arrumadeira que limpa o chão, mas não pega a toalha molhada que você deixou sobre a cama e a põe no cabide.
É que ela limpa o chão (porque sabe que o que está no chão e ninguém está referenciando é lixo mesmo) mas não tira a toalha molhada porque acha que você ainda a está usando (mesmo que você largue o raio da toalha e não passe no seu quarto por um mês 
Se você não remover as referências à janela, ela não morre sozinha. Você precisa pegar o raio da toalha molhada e:
a) OU a jogar no lixo ou deixá-la no chão, ou
b) Deixá-la no cabide.
entanglement, obrigado pelo esclarecimento mas qual a maneira correta de remover esse objeto? definindo ele como null?
Como se faz com todos os objetos em java, definindo todas as variáveis que apontam para ele como null.
Atenção especial no caso de JInternalFrames, pois eles deverão ser removidos do DesktopPane também.
Em java, a única maneira de um objeto ser coletado é se não houver mais referências para ele.
Como se faz com todos os objetos em java, definindo todas as variáveis que apontam para ele como null.
Atenção especial no caso de JInternalFrames, pois eles deverão ser removidos do DesktopPane também.
Em java, a única maneira de um objeto ser coletado é se não houver mais referências para ele.
Aí eu discordo. Não precisa e nem é recomendável ficar definindo todas as variáveis como null explicitamente, pois deixa o código mais difícil de ler. O correto é remover referências quando necessário e deixar as coisas saírem de escopo naturalmente quando não são mais usadas, isto é, usar o mínimo de variáveis globais.
Sei.
É que normalmente em código de GUI as referências para janelas não estão em variáveis locais (que irão naturalmente sair de escopo uma vez que a rotina for concluída - e nesse caso, e apenas nesse caso, o que o ceklock disse tem sentido) e sim em membros da classe que abriu a tal da janela.
Portanto, nesse caso, se a classe precisar fechar a janela, terá de setar explicitamente essa referência para null (obviamente tem de dar o dispose antes
)
Sei.
É que normalmente em código de GUI as referências para janelas não estão em variáveis locais (que irão naturalmente sair de escopo uma vez que a rotina for concluída - e nesse caso, e apenas nesse caso, o que o ceklock disse tem sentido) e sim em membros da classe que abriu a tal da janela.
Portanto, nesse caso, se a classe precisar fechar a janela, terá de setar explicitamente essa referência para null (obviamente tem de dar o dispose antes)
Oi,
Bom… mas não vai fazer tanto efeito assim. Digo isso de forma perceptível, a não ser que a pessoa utilize umas 300 “aberturas e fechamentos” da janela.
Se é que me entende.
Tchauzin!
Sei.
É que normalmente em código de GUI as referências para janelas não estão em variáveis locais (que irão naturalmente sair de escopo uma vez que a rotina for concluída - e nesse caso, e apenas nesse caso, o que o ceklock disse tem sentido) e sim em membros da classe que abriu a tal da janela.
Portanto, nesse caso, se a classe precisar fechar a janela, terá de setar explicitamente essa referência para null (obviamente tem de dar o dispose antes)
É aí que entra o método dispose(), que é a razão desse tópico existir.
Sei.
É que normalmente em código de GUI as referências para janelas não estão em variáveis locais (que irão naturalmente sair de escopo uma vez que a rotina for concluída - e nesse caso, e apenas nesse caso, o que o ceklock disse tem sentido) e sim em membros da classe que abriu a tal da janela.
Portanto, nesse caso, se a classe precisar fechar a janela, terá de setar explicitamente essa referência para null (obviamente tem de dar o dispose antes)
Oi,
Bom… mas não vai fazer tanto efeito assim. Digo isso de forma perceptível, a não ser que a pessoa utilize umas 300 “aberturas e fechamentos” da janela.
Se é que me entende.
Tchauzin!
Exato.
Oi,
A principio, isso me parece um ponto negativo da linguagem (eu não esperava ter que dizer isso um dia).
O Java ou a linguagem deveria interpretar que determinado comando, como o dispose(), deveria remover toda a referência do objeto. A não ser que exista uma razão muito complexa para que isso não aconteça. (?!)
Tchauzin!
Oi,A principio, isso me parece um ponto negativo da linguagem (eu não esperava ter que dizer isso um dia).
O Java ou a linguagem deveria interpretar que determinado comando, como o dispose(), deveria remover toda a referência do objeto. A não ser que exista uma razão muito complexa para que isso não aconteça. (?!)
Tchauzin!
dispose() não faz isso? Pelo que pude entender até agora toda a janela e os componentes associados a ela são liberados da memória se a janela não for mais usada em nenhum outro lugar. Se não tiver mais referências à janela o Garbage Collector vai simplesmente se livrar da janela.
Oi,A principio, isso me parece um ponto negativo da linguagem (eu não esperava ter que dizer isso um dia).
O Java ou a linguagem deveria interpretar que determinado comando, como o dispose(), deveria remover toda a referência do objeto. A não ser que exista uma razão muito complexa para que isso não aconteça. (?!)
Tchauzin!
dispose() não faz isso? Pelo que pude entender até agora toda a janela e os componentes associados a ela são liberados da memória.
Oi,
Eu entendi ao contrário…
Exemplo:
Fechando:
Janela teste = new Janela().setVisible(true);
teste.dispose();
Liberando da memoria:
Janela teste = new Janela().setVisible(true);
teste.dispose();
teste = null;
Tchauzin!
De qualquer forma, é necessário lembrar que toda vez que se usa um sistema operacional como o Windows ou o Linux, você tem o conceito de objetos (“recursos”) que são solicitados ao sistema operacional e cujo ciclo de vida é controlado por ele. Entre esses objetos, estão: janelas, arquivos em disco, sockets, semáforos, memória compartilhada etc. Quando se usa bancos de dados, além disso temos as conexões.
Tais recursos são finitos e devem ser devolvidos depois de usados.
A devolução pode representar um simples fechamento (no caso de arquivos, onde o fechamento indica apenas que você não quer mais lidar com esse arquivo - talvez você também queira efetivar suas ultimas alterações) ou então a prõpria destruição do recurso (como costuma ser o caso das janelas).
No caso do AWT e do Swing, a palavra-chave usada para dispor (devolver) o recurso finito que é a janela é “dispose”.
No caso do java.io, a palavra-chave usada para devolver o recurso (arquivo) é “close”.
O “garbage collector” lida com apenas um tipo de recurso finito, que é a memória usada por seu programa. Não é atribuição dele sair limpando outros tipos de recursos.
Como certo “abuso”, pode-se entretanto abusar do “garbage collector” para que ele, de vez em quando, também limpe outros tipos de recursos (nesse caso, se o recurso estiver em uma classe que implementa o método finalize - http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/Object.html#finalize() .
E é por isso que certos professores ingênuos (daqueles que largam uma toalha molhada em cima da cama e esperam que alguém vá recolhê-la automaticamente) ensinam que arquivos não precisam ser fechados, porque o “garbage collector” irá fazer isso. Isso é um abuso e nunca deve ser feito, na verdade.
Atenção: isso é realmente um “abuso” porque uma classe que implementa esse método indica ao garbage collector que objetos dessa classe que não são mais referenciados são postos em uma lista de objetos a serem “finalizados”, mas essa finalização fica a critério do garbage collector e não é determinística (ou seja, pode ser que um objeto marcado para ser finalizado nunca o seja dentro do tempo de execução de seu programa).
Oi,A principio, isso me parece um ponto negativo da linguagem (eu não esperava ter que dizer isso um dia).
O Java ou a linguagem deveria interpretar que determinado comando, como o dispose(), deveria remover toda a referência do objeto. A não ser que exista uma razão muito complexa para que isso não aconteça. (?!)
Tchauzin!
dispose() não faz isso? Pelo que pude entender até agora toda a janela e os componentes associados a ela são liberados da memória.
Oi,
Eu entendi ao contrário…
Exemplo:
Fechando:
Janela teste = new Janela().setVisible(true); teste.dispose();Liberando da memoria:
Janela teste = new Janela().setVisible(true); teste.dispose(); teste = null;Tchauzin!
Eu sempre fiz assim e vou continuar fazendo:
JFrame f = new JFrame();
...
f.setVisible(true);
...
f.dispose();
Não precisa de f = null;
Oi,A principio, isso me parece um ponto negativo da linguagem (eu não esperava ter que dizer isso um dia).
O Java ou a linguagem deveria interpretar que determinado comando, como o dispose(), deveria remover toda a referência do objeto. A não ser que exista uma razão muito complexa para que isso não aconteça. (?!)
Tchauzin!
dispose() não faz isso? Pelo que pude entender até agora toda a janela e os componentes associados a ela são liberados da memória.
Oi,
Eu entendi ao contrário…
Exemplo:
Fechando:
Janela teste = new Janela().setVisible(true); teste.dispose();Liberando da memoria:
Janela teste = new Janela().setVisible(true); teste.dispose(); teste = null;Tchauzin!
Eu sempre fiz assim e vou continuar fazendo:
JFrame f = new JFrame(); ... f.setVisible(true); ... f.dispose();Não precisa de
f = null;
Oi,
Eu também sempre fiz dessa forma. Mas depois disso:
Como se faz com todos os objetos em java, definindo todas as variáveis que apontam para ele como null.
Atenção especial no caso de JInternalFrames, pois eles deverão ser removidos do DesktopPane também.
Em java, a única maneira de um objeto ser coletado é se não houver mais referências para ele.
Começarei a colocar null. Né?
Tchauzin!
Mas é a ressalva que estou fazendo. Não adianta dar dispose sem limpar as referências.
Ou seja, caso haja variáveis apontando para a janela, elas tem que deixar de apontar.
Não estou falando para sair dando null em tudo. Só no que precisa ser dado (propriedades que não sairão de escopo, por exemplo), ou desregistrar a janela de um DesktopPane.
Caso contrário, ela não será coletada.
Essa é uma confusão comum: o dispose() não tem o poder mágico de fazer o garbage collector coletar o que ainda é referenciado.
Depende do escopo de sua variável f. Se ela se mantiver viva (ou seja, não for criada num método local), o frame também continuará. O dispose() só irá liberar os recursos do SO que o entanglement falou, mas os recursos do java, (dados de classes, labels, imagens, etc) continuarão vivos.
É o caso que ocorre com JInternalFrames, enquanto tiverem uma referência no seu DesktopPane.
PS: O que falei é exatamente o problema que esse usuário está tendo no tópico:
http://www.guj.com.br/java/273455-uso-de-memoria#1436336
O “garbage collector” lida com apenas um tipo de recurso finito, que é a memória usada por seu programa. Não é atribuição dele sair limpando outros tipos de recursos.
Isso é claro. Recursos do sistema não são responsabilidade da JVM e devem ser devidamente encerrados quando não são mais utilizados.
Exatamente. O problema é que janelas consomem uma quantidade imensa de recursos gerenciados, além dos do SO. Então, muita gente dá um dispose() achando que a janela parou de ocupar memória (ou agora ocupa uma quantia insignificante), quando isso não ocorre.
Imagens, por exemplo, são recursos grandes e pesados que são gerenciados pela VM. As informações dos componentes, tais como altura, largura, seu texto, relações, look&feel, etc… também são gerenciadas pela VM.
Então, é errado pensar que um dispose() já eliminou a janela. Se quiser eliminar mesmo da memória, tem que eliminar as referências a ela também. Ou seja, se tiver no seu frame uma propriedade que guarda ali a instância da janela aberta, essa propriedade tem que ser setada para null. Se tiver um DesktopPane, que tambem tem a lista das janelas que ele contém, essa janela tem que ser removida de lá. Se sua janela for listener de outros componentes, você terá que desregistra-la (exceto se esses componentes forem dela mesma). E assim por diante. Só quando a janela não for apontada por ninguém, é que ela será integralmente removida da memória.
O negócio é o seguinte. Salvo alguma rara exceção, na grande maioria dos casos não é necessário setar uma variável como null. A máquina virtual sabe muito bem quando uma variável/atributo não é usado.
O dispose() serve justamente para “desamarrar” a janela. Se ela nunca mais for usada ela vai “sumir” da memória até que algum dia seja chamado um método setVisible() ou algo parecido.
E tudo que está dentro da janela pertence à janela e vai “sumir” junto com ela. Se tem um botão adicionado numa janela e eu matar a janela eu não preciso remover o botão da janela para ele ser removido da memória.
http://docs.oracle.com/javase/6/docs/api/java/awt/Window.html#dispose()
Por mim podem encerrar esse tópico. A conversa já tá mudando o foco. Minha dúvida já foi esclarecida.
Uma curiosidade.
Crie um programa que aloque 100 strings cada uma ocupando 1 MB de memória (ou seja, cada uma delas contém 500 mil caracteres). Ponha-as em um array e imprima a quantidade de memória usada pelo programa. Para garantir que é a memória mesmo, antes de imprimir, execute um System.gc, espere 2 segundos, e entáo execute outro System.gc.
A seguir, crie um outro array de 100 posicóes contendo substrings dessas strings grandes (digamos da pposiçao 1000 até a 2000). Imprima a mem[oria usada. Você deve ver que a quantidade praticamente não se alterou.
Então, limpe o primeiro array (aquele das strings grandes). Execute um System.gc e veja quanta memória está sendo usada.
Perguntas:
Uma curiosidade.Crie um programa que aloque 100 strings cada uma ocupando 1 MB de memória (ou seja, cada uma delas contém 500 mil caracteres). Ponha-as em um array e imprima a quantidade de memória usada pelo programa. Para garantir que é a memória mesmo, antes de imprimir, execute um System.gc, espere 2 segundos, e entáo execute outro System.gc.
A seguir, crie um outro array de 100 posicóes contendo substrings dessas strings grandes (digamos da pposiçao 1000 até a 2000). Imprima a mem[oria usada. Você deve ver que a quantidade praticamente não se alterou.
Então, limpe o primeiro array (aquele das strings grandes). Execute um System.gc e veja quanta memória está sendo usada.
Perguntas:
- a quantidade de memória usada caiu ou não?
- Por que é que isso ocorreu? (Dica: leia o fonte da classe String, método substring)
- Como evitar esse problema esquisito?
Enfim, esse não é o foco desse tópico, mas tudo bem.
O negócio é o seguinte. Salvo alguma rara exceção, na grande maioria dos casos não é necessário setar uma variável como null. A máquina virtual sabe muito bem quando uma variável/atributo não é mais usado por ninguém.
Eu só discordo de que isso seja exceção, e mais ainda que seja raro.
Já atendi dezenas de tópicos no GUJ com exatamente esse problema.
public class Menu {
private Janela1 janela1;
...
public void abrirJanela1() {
if (janela1 == null) {
janela1 = new Janela1();
janela1.setVisible(true);
}
}
}
Você já terá que deixar janela1 null após o dispose(). É ainda mais comum no caso de ser um JInternalPane, uma vez que ele é associado a um DesktopPane. O dispose() não remove a janela do DesktopPane e, portanto, uma referência como a acima se faz necessária. É também necessária uma atitude explícita do programador.
É muita ingenuidade achar que uma variável que nunca mais é usada vai continuar ali de bobeira.
A nunca usada continua sim. A nunca referenciada é que não. A única regra existente é que para uma variável ser removida da memória, ela não pode ser alcançável a partir de nenhuma thread. Se ela é alcançavel, aí ferrou.
Um caso clássico é um JInternalFrame invisível, sem que haja uma referência explícita para deixa-lo visível novamente. Caso o programador não se dê ao trabalho de procurar a referência que está dentro do JDesktopPane e remove-la, ela ficará lá, sem uso e invisível para sempre, ocupando memória.
O dispose() serve justamente para "desamarrar" a janela. Se ela nunca mais for usada ela vai sumir da memória até que algum dia seja chamado um método setVisible() ou algo parecido.
Como já foi dito, ele não retira toda a janela da memória, só parte dela. Ele só desaloca os recursos da janela associados ao SO. Se ainda existirem referências para a janela, ela continua na memória. O dispose() não cria nenhum tipo de exceção no garbage collector.
Como a própria documentação que você linkou diz:
Releases all of the native screen resources used by this Window, its subcomponents, and all of its owned children. That is, the resources for these Components will be destroyed, any memory they consume will be returned to the OS, and they will be marked as undisplayable.
Note que ele está falando de "native resources". Os recursos do Java ainda tem que existir na memória, até para ele saber como recriar recursos nativos caso um setVisible(true) seja novamente dado. Esses recursos são todas as variáveis, textos de labels, imagens, enfim, toda informação necessária para reconstruir a janela no SO. E isso nem sempre representa pouca memória.
Outros erros comuns que mantém a janela ativa:
1. Ter componentes dentro dela que são listeners de coisas fora da janela;
2. Ter variáveis estáticas apontando para a janela ou algum de seus componentes.
Esse link fala sobre essa história de setar variáveis para null. Fonte: Java theory and practice: Garbage collection and performance [url]http://www.ibm.com/developerworks/java/library/j-jtp01274/index.html[/url]
Explicit nullingExplicit nulling is simply the practice of setting reference objects to null when you are finished with them. The idea behind nulling is that it assists the garbage collector by making objects unreachable earlier. Or at least that's the theory.
Listing 3. Avoiding object loitering in a stack implementation
There is one case where the use of explicit nulling is not only helpful, but virtually required, and that is where a reference to an object is scoped more broadly than it is used or considered valid by the program's specification. This includes cases such as using a static or instance field to store a reference to a temporary buffer, rather than a local variable, or using an array to store references that may remain reachable by the runtime but not by the implied semantics of the program. Consider the class in Listing 3, which is an implementation of a simple bounded stack backed by an array. When pop() is called, without the explicit nulling in the example, the class could cause a memory leak (more properly called "unintentional object retention," or sometimes called "object loitering") because the reference stored in stack[top+1] is no longer reachable by the program, but still considered reachable by the garbage collector.public class SimpleBoundedStack { private static final int MAXLEN = 100; private Object stack[] = new Object[MAXLEN]; private int top = -1; public void push(Object p) { stack [++top] = p;} public Object pop() { Object p = stack [top]; stack [top--] = null; // explicit null return p; } }In the September 1997 "Java Developer Connection Tech Tips" column (see Resources), Sun warned of this risk and explained how explicit nulling was needed in cases like the pop() example above. Unfortunately, programmers often take this advice too far, using explicit nulling in the hope of helping the garbage collector. But in most cases, it doesn't help the garbage collector at all, and in some cases, it can actually hurt your program's performance.
Ceklock, como falei 3 vezes nesse tópico, não estou falando de definir variáveis que saem de escopo para null. Mas variáveis que se mantém no escopo, como no exemplo que citei anteriormente.
Definir variáveis que saem de escopo para null é desnecessário, pois essas variáveis deixarão de existir.
Aliás, o texto que você linkou, fala exatamente disso:
Ceklock, como falei 3 vezes nesse tópico, não estou falando de definir variáveis que saem de escopo para null. Mas variáveis que se mantém no escopo, como no exemplo que citei anteriormente.Definir variáveis que saem de escopo para null é desnecessário, pois essas variáveis deixarão de existir.
Aliás, o texto que você linkou, fala exatamente disso:
Esse caso que eles citam é uma exceção.
"Unfortunately, programmers often take this advice too far, using explicit nulling in the hope of helping the garbage collector. But in most cases, it doesn’t help the garbage collector at all, and in some cases, it can actually hurt your program’s performance. "
É isso o que vejo por aqui.
Com certeza, mas não é do que eu estou falando! Já repeti diversas vezes que você deve deixar nulo variáveis que estejam em escopo. E, pela forma que janelas são construídas, isso não é exceção.
Basta ver o código que postei anteriormente, que é uma das formas comuns de se fazer interfaces gráficas.
É muito comum que a janela contendo o menu da aplicação fique ativa. Se ela tiver propriedades para as janelas que ela abre, essas janelas também estarão na memória, estejam elas visíveis ou não.
O ideal é não guardar essas janelas propriedades. Mas caso você tenha um JDesktopPane, você tem um problema!
O JDesktopPane vai guardar essas referências para você.
O negócio é o seguinte. Salvo alguma rara exceção, na grande maioria dos casos não é necessário setar uma variável como null. A máquina virtual sabe muito bem quando uma variável/atributo não é mais usado por ninguém.Eu só discordo de que isso seja exceção, e mais ainda que seja raro.
Se você tem um JFrame assim (como o Visual Editor sugeria):
Já atendi dezenas de tópicos no GUJ com exatamente esse problema.public class Menu { private Janela1 janela1; ... public void abrirJanela1() { if (janela1 == null) { janela1 = new Janela1(); janela1.setVisible(true); } } }Você já terá que deixar janela1 null após o dispose(). É ainda mais comum no caso de ser um JInternalPane, uma vez que ele é associado a um DesktopPane. O dispose() não remove a janela do DesktopPane e, portanto, uma referência como a acima se faz necessária. É também necessária uma atitude explícita do programador.
Por que terá que deixar janela1 null?
Nesse caso que você citou acima quando chamar abrirJanela1() a próxima janela vai automaticamente ocupar o lugar da anterior (a variável janela1 vai receber um novo objeto), e a anterior vai perder referencia, desde que vc chame dispose() ao fechar a janela (use setDefaultCloseOperation(DISPOSE_ON_CLOSE) ).
E um JInternalFrame não é uma janela de verdade, é um componente leve. E pra que ficar setando janelas como null? O melhor é deixar só invisivel mesmo, e reutilizar depois. Afinal, é uma interface gráfica. Tu só vai se livrar de janelas se for estritamente necessário.
No fim tem que cuidar do que realmente é um gargalo pra memória e que poderia gerar um memory leak.
Por que terá que deixar janela1 null?Nesse caso que você citou acima quando chamar abrirJanela1() a próxima janela vai automaticamente ocupar o lugar da anterior (a variável janela1 vai receber um novo objeto), e a anterior vai perder referencia, desde que vc chame dispose() ao fechar a janela (use setDefaultCloseOperation(DISPOSE_ON_CLOSE) ).
Você deve setar como null porque aquela variável não sai do escopo. Se o menu tiver 50 janelas, e cada uma for aberta uma vez, haverá 50 janelas na memória ao final do processo, mesmo que todas tenham sido fechadas!
De qualquer forma, com o que você falou, só vai haver a coleta da memória da janela anterior, quando a nova for aberta. Ou seja, no sistema, haverá pelo menos uma janela daquele tipo ocupando memória, a partir do momento que ela for aberta a primeira vez.
E estamos falando exatamente sobre se certificar que essa memória foi coletada!
Eu até concordo que, no geral, você pode usar a memória dessa forma relaxada, pois janelas tipicamente não ocupam tanta memória assim. Mas não é disso que o tópico se trata. Estamos falando no escopo do dispose() e em como garantir que toda a memória da janela foi desocupada.
E um JInternalFrame não é uma janela de verdade, é um componente leve. E pra que ficar setando janelas como null? O melhor é deixar só invisivel mesmo, e reutilizar depois. Afinal, é uma interface gráfica. Tu só vai se livrar de janelas se for estritamente necessário.
Se ele é leve ou não depende dos componentes que tem dentro. No post do problema que citei, o usuário abria uma imagem, um recurso grande e pesado. O frame invisível continuará com a imagem lá. Se a janela carregou em suas variáveis internas vídeos, música ou outros recursos pesados, esses recursos vão continuar lá, ocupando memória junto.
Por isso é importante saber quando e como janelas são realmente limpas, e onde é o papel do dispose, onde é o do gc() e como garantir que os dois rodem adequadamente.
Verdade. Mas é bom saber que o que fazer caso você perceba que o leak é nas janelas fechadas. 
Você deve setar como null porque aquela variável não sai do escopo. Se o menu tiver 50 janelas, e cada uma for aberta uma vez, haverá 50 janelas na memória ao final do processo, mesmo que todas tenham sido fechadas!De qualquer forma, com o que você falou, só vai haver a coleta da memória da janela anterior, quando a nova for aberta. Ou seja, no sistema, haverá pelo menos uma janela daquele tipo ocupando memória, a partir do momento que ela for aberta a primeira vez.
Tá bom. Não vou ficar discutindo. Eu particularmente prefiro sites como o http://www.stackoverflow.com onde tem mais moderação. Ao invés de ficar discutindo devíamos mostrar mais referências/fontes e fazer testes usando profilers.
E sobre componentes leves e pesados, é esse o significado:
“A heavyweight component is one that is associated with its own native screen resource (commonly known as a peer). A lightweight component is one that “borrows” the screen resource of an ancestor (which means it has no native resource of its own – so it’s “lighter”).” - http://java.sun.com/products/jfc/tsc/articles/mixing/
Não percebi que você falou em “componente leve” se referindo a lightweight. Até porque, todos os componentes do Swing são lightweight, e não só o JInternalFrame:
http://docs.oracle.com/javase/1.4.2/docs/api/javax/swing/package-summary.html
Não entendi o que você quis dizer com o stackoverflow ter mais moderação. Nossa discussão foi estritamente técnica, e encontra-se discussões desse tipo por lá também. Eu não me senti ofendido, nem irritado, pelos seus comentários, e nem “trocamos elogios”.
De fato, eu concordo com muitos dos seus argumentos, como o fato de não ficar nulificando variáveis locais, e não ficar otimizando sem um profiler. Inclusive, já dei as mesmas dicas aqui no GUJ, para bastante gente. E sou um grande fã dos artigos do Goetz. 
Entretanto, eu só estava deixando claro como funciona o mecanismo de liberação das janelas, sem entrar no mérito de se isso seria ou não uma boa prática sempre. É um erro muito comum acreditar que o dispose() libera toda a memória ocupada por uma janela, mesmo aquela pertencente à VM (como se ele magicamente ampliasse as capacidades do coletor de lixo).
Não percebi que você falou em “componente leve” se referindo a lightweight. Até porque, todos os componentes do Swing são lightweight, e não só o JInternalFrame:
http://docs.oracle.com/javase/1.4.2/docs/api/javax/swing/package-summary.htmlNão entendi o que você quis dizer com o stackoverflow ter mais moderação. Nossa discussão foi estritamente técnica, e encontra-se discussões desse tipo por lá também. Eu não me senti ofendido, nem irritado, pelos seus comentários, e nem “trocamos elogios”.
De fato, eu concordo com muitos dos seus argumentos, como o fato de não ficar nulificando variáveis locais, e não ficar otimizando sem um profiler. Inclusive, já dei as mesmas dicas aqui no GUJ, para bastante gente. E sou um grande fã dos artigos do Goetz.
Entretanto, eu só estava deixando claro como funciona o mecanismo de liberação das janelas, sem entrar no mérito de se isso seria ou não uma boa prática sempre. É um erro muito comum acreditar que o dispose() libera toda a memória ocupada por uma janela, mesmo aquela pertencente à VM (como se ele magicamente ampliasse as capacidades do coletor de lixo).
O que eu quero dizer é que aqui as discussões acabam ficando muito longas.
Não percebi que você falou em “componente leve” se referindo a lightweight. Até porque, todos os componentes do Swing são lightweight, e não só o JInternalFrame:
http://docs.oracle.com/javase/1.4.2/docs/api/javax/swing/package-summary.html
Não. Não são todos os componentes do Swing que são lightweight.
The only heavyweight components used in Swing are:swing.JFrame
swing.JDialog
swing.JWindow
swing.JApplet
All AWT components (awt.*), except those noted below.
fonte: http://java.sun.com/products/jfc/tsc/articles/containers/#heavyweights_and
Ah sim, claro. Você quis dizer que o JInternalFrame são janelas lightweight. Já que janelas são, tipicamente, os únicos componentes heavyweight do Swing.
Aí faz todo sentido. 
Na verdade, foi o que pensei poucos segundos após postar para vc a resposta.
Ah sim, claro. Você quis dizer que o JInternalFrame são janelas lightweight. Já que janelas são, tipicamente, os únicos componentes heavyweight do Swing.
Aí faz todo sentido.![]()
Na verdade, foi o que pensei poucos segundos após postar para vc a resposta.
É, exatamente.
E eu estava fazendo uns testes com o profiler do NetBeans sobre esse assunto de janelas e etc… Mas não cheguei a uma conclusão ainda.
Sobre o esquema de variáveis não usadas que eu falei, é isso que eu li há algum tempo atrás:
The HotSpot compiler is smart enough not to generate code for dead variables.
public static void method(int arg) {
int value = arg + 25;
}
In the method above, the local variable is never used, so there’s no reason to compute its value. So then the method body is empty again and when the code gets compiled (and inlined, because we removed enough code to make it small enough for inlining) it turns into an empty method again.
fonte: http://www.oracle.com/technetwork/java/hotspotfaq-138619.html