Normalmente, não.
Mas como todas as coisas: depende. O GC em Java atualmente é MUITO bom e tudo deve ser limpo logo depois que não estiver mais acessível. Isso ocorre logo após deixar um método para variáveis locais e quando uma instância de classe não é mais referenciada para campos.
Você só precisa anular explicitamente se souber que permaneceria referenciado de outra forma. Por exemplo, uma matriz que é mantida. Você pode anular os elementos individuais da matriz quando eles não forem mais necessários.
Por exemplo, este código de ArrayList:
public E remove(int index) {
RangeCheck(index);
modCount++;
E oldValue = (E) elementData[index];
int numMoved = size - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
elementData[--size] = null;
return oldValue;
}
Além disso, anular explicitamente um objeto não fará com que um objeto seja coletado antes do que se ele simplesmente saísse do escopo naturalmente, desde que nenhuma referência permanecesse.
Ambos:
void foo() {
Object o = new Object();
}
e:
void foo() {
Object o = new Object();
o = null;
}
São funcionalmente equivalentes.
System.gc()
, eles são removidos (desde que não haja outras referências apontando para esse objeto).Na minha experiência, na maioria das vezes, as pessoas anulam as referências por paranóia, não por necessidade. Aqui está uma orientação rápida:
Se o objeto A fizer referência ao objeto B e você não precisar mais dessa referência e o objeto A não for elegível para coleta de lixo, você deve anular explicitamente o campo. Não há necessidade de anular um campo se o objeto delimitador estiver recebendo a coleta de lixo de qualquer maneira. Anular campos em um método dispose () é quase sempre inútil.
Não há necessidade de anular as referências de objeto criadas em um método. Eles serão apagados automaticamente assim que o método terminar. A exceção a essa regra é se você estiver executando um método muito longo ou algum loop massivo e precisar garantir que algumas referências sejam apagadas antes do final do método. Novamente, esses casos são extremamente raros.
Eu diria que na grande maioria das vezes você não precisará anular as referências. Tentar ser mais esperto que o coletor de lixo é inútil. Você acabará com um código ineficiente e ilegível.
fonte
Um bom artigo é o horror da codificação de hoje .
A forma como o GC trabalha é procurando por objetos que não tenham nenhum indicador para eles, a área de sua pesquisa é heap / stack e quaisquer outros espaços que eles tenham. Portanto, se você definir uma variável como nula, o objeto real agora não é apontado por ninguém e, portanto, pode ser GC.
Mas como o GC pode não funcionar naquele exato instante, você pode não estar comprando nada. Mas se o seu método for bastante longo (em termos de tempo de execução), pode valer a pena, pois você estará aumentando suas chances de GC coletar esse objeto.
O problema também pode ser complicado com otimizações de código, se você nunca usar a variável depois de defini-la como nula, seria uma otimização segura remover a linha que define o valor como nulo (uma instrução a menos para executar). Portanto, você pode não estar realmente obtendo nenhuma melhora.
Resumindo, sim, pode ajudar, mas não será determinístico .
fonte
Pelo menos em java, não é programação vodu. Quando você cria um objeto em java usando algo como
Foo bar = new Foo();
você faz duas coisas: primeiro, você cria uma referência a um objeto e, segundo, cria o próprio objeto Foo. Enquanto essa referência ou outra existir, o objeto específico não pode ser gc'd. no entanto, quando você atribui nulo a essa referência ...
bar = null ;
e assumindo que nada mais tenha uma referência ao objeto, ele é liberado e disponibilizado para gc na próxima vez que o coletor de lixo passar.
fonte
Depende.
Em geral, quanto mais curto você manter as referências aos seus objetos, mais rápido eles serão coletados.
Se seu método leva, digamos, 2 segundos para ser executado e você não precisa mais de um objeto após um segundo de execução do método, faz sentido limpar todas as referências a ele. Se o GC vir isso depois de um segundo, seu objeto ainda está referenciado, da próxima vez ele pode verificar em um minuto ou assim.
De qualquer forma, definir todas as referências como nulas por padrão é para mim uma otimização prematura e ninguém deve fazer isso, a menos que em casos raros específicos em que diminua o consumo de memória de forma mensurável.
fonte
Definir explicitamente uma referência como nulo em vez de apenas deixar a variável sair do escopo não ajuda o coletor de lixo, a menos que o objeto mantido seja muito grande, onde defini-lo como nulo assim que terminar é uma boa ideia.
Geralmente, definir referências como null significa para o LEITOR do código com o qual este objeto está completamente concluído e não deve se preocupar mais com ele.
Um efeito semelhante pode ser obtido introduzindo um escopo mais estreito, colocando um conjunto extra de suportes
{ int l; { // <- here String bigThing = ....; l = bigThing.length(); } // <- and here }
isso permite que o bigThing seja coletado como lixo logo após deixar as chaves aninhadas.
fonte
public class JavaMemory { private final int dataSize = (int) (Runtime.getRuntime().maxMemory() * 0.6); public void f() { { byte[] data = new byte[dataSize]; //data = null; } byte[] data2 = new byte[dataSize]; } public static void main(String[] args) { JavaMemory jmp = new JavaMemory(); jmp.f(); } }
Acima dos lances do programa
OutOfMemoryError
. Se você descomentardata = null;
, oOutOfMemoryError
é resolvido. É sempre uma boa prática definir a variável não utilizada como nulafonte
Eu estava trabalhando em um aplicativo de videoconferência uma vez e notei uma enorme diferença enorme no desempenho quando dediquei um tempo para referências nulas assim que não precisei mais do objeto. Isso foi em 2003-2004 e só posso imaginar que o GC ficou ainda mais inteligente desde então. No meu caso, eu tinha centenas de objetos entrando e saindo do escopo a cada segundo, então percebi o GC quando ele entrava em ação periodicamente. No entanto, depois que fiz questão de objetos nulos, o GC parou de pausar meu aplicativo.
Então, depende do que você está fazendo ...
fonte
Sim.
De "The Pragmatic Programmer" p.292:
Ao definir uma referência para NULL, você reduz o número de ponteiros para o objeto em um ... (o que permitirá que o coletor de lixo o remova)
fonte
Presumo que o OP está se referindo a coisas como estas:
private void Blah() { MyObj a; MyObj b; try { a = new MyObj(); b = new MyObj; // do real work } finally { a = null; b = null; } }
Nesse caso, a VM não os marcaria para GC assim que saíssem do escopo?
Ou, de outra perspectiva, definir explicitamente os itens como nulos faria com que eles obtivessem GC antes que fariam se simplesmente saíssem do escopo? Em caso afirmativo, a VM pode gastar tempo GC'ing o objeto quando a memória não é necessária de qualquer maneira, o que poderia causar pior desempenho no uso da CPU porque seria GC'ing mais cedo.
fonte
null
influencie o comportamento do GC." Depende "
Eu não sei sobre Java, mas em .net (C #, VB.net ...) geralmente não é necessário atribuir um nulo quando você não precisa mais de um objeto.
No entanto, observe que "geralmente não é necessário".
Ao analisar seu código, o compilador .net faz uma boa avaliação do tempo de vida da variável ... para dizer com precisão quando o objeto não está mais sendo usado. Então, se você escrever obj = null, pode parecer que o obj ainda está sendo usado ... neste caso, é contraproducente atribuir um nulo.
Existem alguns casos em que pode realmente ajudar atribuir um nulo. Um exemplo é que você tem um código enorme que é executado por um longo tempo ou um método que está sendo executado em uma thread diferente ou algum loop. Nesses casos, pode ser útil atribuir nulo para que seja fácil para o GC saber que não está mais sendo usado.
Não existe uma regra rígida e rápida para isso. Indo pelo acima, coloque atribuições nulas em seu código e execute um criador de perfil para ver se isso ajuda de alguma forma. Muito provavelmente você não verá um benefício.
Se for um código .net que você está tentando otimizar, então minha experiência tem sido que cuidar bem dos métodos Dispose e Finalize é na verdade mais benéfico do que se preocupar com nulos.
Algumas referências sobre o tema:
http://blogs.msdn.com/csharpfaq/archive/2004/03/26/97229.aspx
http://weblogs.asp.net/pwilson/archive/2004/02/20/77422.aspx
fonte
Mesmo se anular a referência fosse um pouco mais eficiente, valeria a pena ter que salpicar seu código com essas nulificações horríveis? Eles seriam apenas desordem e obscureceriam o código de intenção que os contém.
É uma base de código rara que não tem melhor candidato para otimização do que tentar superar o coletor de lixo (mais raros ainda são os desenvolvedores que conseguem superá-lo). Provavelmente, seus esforços serão mais bem empregados em outro lugar, abandonando aquele analisador Xml crufty ou encontrando alguma oportunidade de cache de computação. Essas otimizações serão mais fáceis de quantificar e não exigem que você suja sua base de código com ruído.
fonte
Na execução futura de seu programa, os valores de alguns membros de dados serão usados para computar uma saída visível externa ao programa. Outros podem ou não ser usados, dependendo das entradas futuras (e impossíveis de prever) para o programa. Outros membros de dados podem ter a garantia de não serem usados. Todos os recursos, incluindo memória, alocados para os dados não utilizados são desperdiçados. O trabalho do coletor de lixo (GC) é eliminar essa memória desperdiçada. Seria desastroso para o GC eliminar algo que era necessário, então o algoritmo usado pode ser conservador, retendo mais do que o mínimo estrito. Ele pode usar otimizações heurísticas para melhorar sua velocidade, ao custo de reter alguns itens que não são realmente necessários. Existem muitos algoritmos potenciais que o GC pode usar. Portanto, é possível que alterações feitas em seu programa, e que não afetam a correção de seu programa, podem, no entanto, afetar a operação do GC, tornando-o mais rápido para fazer o mesmo trabalho ou para identificar itens não utilizados mais cedo. Portanto, esse tipo de mudança, definindo uma referência de objeto inusitado
null
, em teoria nem sempre é vodu.Isso é vodu? Segundo informações, há partes do código da biblioteca Java que fazem isso. Os escritores desse código são muito melhores do que os programadores médios e conhecem ou cooperam com programadores que conhecem detalhes das implementações do coletor de lixo. Assim que sugere que é , por vezes, um benefício.
fonte
Como você disse, existem otimizações, ou seja, a JVM sabe o local quando a variável foi usada pela última vez e o objeto referenciado por ela pode ser GCed logo após este último ponto (ainda em execução no escopo atual). Portanto, anular as referências na maioria dos casos não ajuda o GC.
Mas pode ser útil para evitar o problema do "nepotismo" (ou "lixo flutuante") ( leia mais aqui ou assista ao vídeo ). O problema existe porque a pilha é dividida nas gerações Velha e Jovem e existem diferentes mecanismos de GC aplicados: Minor GC (que é rápido e acontece frequentemente para limpar o jovem gen) e Major Gc (que causa uma pausa mais longa para limpar o Old gen). O "nepotismo" não permite que o lixo da geração jovem seja coletado se for referenciado por lixo já adquirido por uma geração antiga.
Para evitar o nepotismo, é uma boa ideia anular as referências de um objeto que deve ser removido. Você pode ver essa técnica aplicada nas classes JDK: LinkedList e LinkedHashMap
private E unlinkFirst(Node<E> f) { final E element = f.item; final Node<E> next = f.next; f.item = null; f.next = null; // help GC // ... }
fonte