Existe uma maneira de liberar memória em Java, semelhante à free()
função de C ? Ou definir o objeto como nulo e confiar na GC é a única opção?
Existe uma maneira de liberar memória em Java, semelhante à free()
função de C ? Ou definir o objeto como nulo e confiar na GC é a única opção?
Respostas:
Java usa memória gerenciada; portanto, a única maneira de alocar memória é usando o new
operador, e a única maneira de desalocar memória é contando com o coletor de lixo.
Este white paper de gerenciamento de memória (PDF) pode ajudar a explicar o que está acontecendo.
Você também pode ligar System.gc()
para sugerir que o coletor de lixo seja executado imediatamente. No entanto, o Java Runtime toma a decisão final, não o seu código.
De acordo com a documentação Java ,
Chamar o método gc sugere que a Java Virtual Machine dedique esforços para reciclar objetos não utilizados, a fim de disponibilizar a memória que eles ocupam atualmente para reutilização rápida. Quando o controle retorna da chamada de método, a Java Virtual Machine se esforça ao máximo para recuperar o espaço de todos os objetos descartados.
System.gc()
completamente.
Parece que ninguém mencionou a definição explícita de referências a objetos null
, que é uma técnica legítima para "liberar" a memória que você pode querer considerar.
Por exemplo, digamos que você tenha declarado um List<String>
no início de um método que cresceu em tamanho para ser muito grande, mas só foi necessário até a metade do método. Nesse ponto, você pode definir a referência de lista null
para permitir que o coletor de lixo potencialmente recupere esse objeto antes que o método seja concluído (e a referência fica fora do escopo de qualquer maneira).
Observe que raramente uso essa técnica na realidade, mas vale a pena considerar ao lidar com estruturas de dados muito grandes.
System.gc();
Executa o coletor de lixo.
Chamar o método gc sugere que a Java Virtual Machine dedique esforços para reciclar objetos não utilizados, a fim de disponibilizar a memória que eles ocupam atualmente para reutilização rápida. Quando o controle retorna da chamada do método, a Java Virtual Machine se esforça ao máximo para recuperar o espaço de todos os objetos descartados.
Não recomendado.
Edit: eu escrevi a resposta original em 2009. Agora é 2015.
Os coletores de lixo ficaram cada vez melhores nos ~ 20 anos que o Java existe. Neste ponto, se você estiver chamando manualmente o coletor de lixo, convém considerar outras abordagens:
* "Pessoalmente, confio nas variáveis de nulidade como espaço reservado para futura exclusão adequada. Por exemplo, dedico um tempo para anular todos os elementos de uma matriz antes de excluir (tornar nula) a própria matriz."
Isso é desnecessário. A maneira como o Java GC funciona é encontrar objetos que não têm referência a eles; portanto, se eu tiver um Objeto x com uma referência (= variável) a que aponte para ele, o GC não o excluirá, porque há uma referência para esse objeto:
a -> x
Se você nulo a, isso acontece:
a -> null
x
Portanto, agora x não tem uma referência apontando para ele e será excluído. O mesmo acontece quando você define a para fazer referência a um objeto diferente de x.
Portanto, se você tem um arr arr que faz referência aos objetos x, ye z e uma variável a que faz referência ao array, fica assim:
a -> arr -> x
-> y
-> z
Se você nulo a, isso acontece:
a -> null
arr -> x
-> y
-> z
Portanto, o GC considera arr como não tendo nenhuma referência definida e a exclui, o que fornece essa estrutura:
a -> null
x
y
z
Agora o GC encontra x, ye z e os exclui também. Anular cada referência na matriz não melhorará nada, apenas consumirá o tempo e o espaço da CPU no código (dito isso, não será prejudicial além disso. O GC ainda poderá executar da maneira que deve )
Um motivo válido para querer liberar memória de qualquer programa (java ou não) é disponibilizar mais memória para outros programas no nível do sistema operacional. Se meu aplicativo java estiver usando 250 MB, convém forçá-lo a 1 MB e disponibilizar os 249 MB para outros aplicativos.
Para estender a resposta e o comentário de Yiannis Xanthopoulos e Hot Licks (desculpe, ainda não posso comentar!), Você pode definir opções de VM como este exemplo:
-XX:+UseG1GC -XX:MinHeapFreeRatio=15 -XX:MaxHeapFreeRatio=30
No meu jdk 7, isso liberará memória não utilizada da VM se mais de 30% do heap ficar livre após o GC quando a VM estiver ociosa. Você provavelmente precisará ajustar esses parâmetros.
Embora eu não tenha visto isso enfatizado no link abaixo, observe que alguns coletores de lixo podem não obedecer a esses parâmetros e, por padrão, o java pode escolher um deles para você, caso você tenha mais de um núcleo (daí o argumento UseG1GC acima )
Atualização: Para o java 1.8.0_73, vi a JVM ocasionalmente liberar pequenas quantidades com as configurações padrão. Parece fazê-lo apenas se ~ 70% da pilha não for usada .. não sei se seria mais agressivo se o sistema operacional estivesse com pouca memória física.
Eu fiz experiências sobre isso.
É verdade que System.gc();
apenas sugere executar o Garbage Collector.
Mas chamar System.gc();
depois de definir todas as referências para null
, melhorará o desempenho e a ocupação da memória.
Se você realmente deseja alocar e liberar um bloco de memória, pode fazer isso com ByteBuffers diretos. Existe até uma maneira não portátil de liberar a memória.
No entanto, como foi sugerido, apenas porque você precisa liberar memória em C, não significa que seja uma boa ideia fazer isso.
Se você acha que realmente tem um bom caso de uso gratuito (), inclua-o na pergunta para que possamos ver o que você está tentando fazer, é bem provável que exista uma maneira melhor.
Inteiramente de javacoffeebreak.com/faq/faq0012.html
Um encadeamento de baixa prioridade cuida da coleta de lixo automaticamente para o usuário. Durante o tempo ocioso, o encadeamento pode ser chamado e pode começar a liberar memória alocada anteriormente para um objeto em Java. Mas não se preocupe - ele não excluirá seus objetos!
Quando não há referências a um objeto, torna-se um jogo justo para o coletor de lixo. Em vez de chamar alguma rotina (como livre em C ++), você simplesmente atribui todas as referências ao objeto para null, ou atribui uma nova classe à referência.
Exemplo:
public static void main(String args[]) { // Instantiate a large memory using class MyLargeMemoryUsingClass myClass = new MyLargeMemoryUsingClass(8192); // Do some work for ( .............. ) { // Do some processing on myClass } // Clear reference to myClass myClass = null; // Continue processing, safe in the knowledge // that the garbage collector will reclaim myClass }
Se o seu código estiver prestes a solicitar uma grande quantidade de memória, convém solicitar que o coletor de lixo comece a recuperar espaço, em vez de permitir que faça isso como um encadeamento de baixa prioridade. Para fazer isso, adicione o seguinte ao seu código
System.gc();
O coletor de lixo tentará recuperar o espaço livre e seu aplicativo poderá continuar executando, com o máximo de memória possível (os problemas de fragmentação da memória podem se aplicar a determinadas plataformas).
No meu caso, como meu código Java deve ser portado para outras linguagens em um futuro próximo (principalmente C ++), eu pelo menos quero prestar um bom serviço para liberar memória adequadamente, para ajudar no processo de portabilidade posteriormente.
Pessoalmente, confio nas variáveis de nulidade como espaço reservado para futura exclusão adequada. Por exemplo, dedico um tempo para anular todos os elementos de uma matriz antes de realmente excluir (tornar nulo) a própria matriz.
Mas meu caso é muito particular e sei que estou recebendo resultados de desempenho ao fazer isso.
* "Por exemplo, digamos que você tenha declarado uma lista no início de um método que cresceu em tamanho para ser muito grande, mas só era necessária até a metade do método. Nesse momento, era possível definir a referência da lista como nula para permitir que o coletor de lixo potencialmente recupere esse objeto antes que o método seja concluído (e a referência fica fora do escopo de qualquer maneira). " *
Isso está correto, mas esta solução pode não ser generalizável. Ao definir uma referência de objeto de lista como nula - disponibilizará memória para coleta de lixo, isso é válido apenas para um objeto de lista de tipos primitivos. Se, em vez disso, o objeto List contiver tipos de referência, a configuração do objeto List = null não desreferirá - qualquer um dos tipos de referência contidos - na lista. Nesse caso, definir o objeto List = null tornará órfão os tipos de referência contidos cujos objetos não estarão disponíveis para coleta de lixo, a menos que o algoritmo de coleta de lixo seja inteligente o suficiente para determinar que os objetos foram órfãos.
Por meio do java, fornece coleta de lixo automática às vezes, você deseja saber o tamanho do objeto e a quantidade restante. Memória livre usando programaticamente import java.lang;
e Runtime r=Runtime.getRuntime();
obter valores de memória usando mem1=r.freeMemory();
a memória livre para chamar o r.gc();
método e a chamadafreeMemory()
A recomendação do JAVA é atribuir a null
De https://docs.oracle.com/cd/E19159-01/819-3681/abebi/index.html
A atribuição explícita de um valor nulo a variáveis que não são mais necessárias ajuda o coletor de lixo a identificar as partes da memória que podem ser recuperadas com segurança. Embora o Java forneça gerenciamento de memória, ele não impede vazamentos ou uso excessivo de memória.
Um aplicativo pode induzir vazamentos de memória, não liberando referências a objetos. Isso evita que o coletor de lixo Java recupere esses objetos e resulta no aumento da quantidade de memória usada. Anular explicitamente referências a variáveis após seu uso permite que o coletor de lixo recupere memória.
Uma maneira de detectar vazamentos de memória é empregar ferramentas de criação de perfil e tirar instantâneos de memória após cada transação. Um aplicativo sem vazamento no estado estacionário mostrará uma memória ativa ativa constante após a coleta de lixo.