JavaRush /Blogue Java /Random-PT /Mais sobre o coletor de lixo em Java

Mais sobre o coletor de lixo em Java

Publicado no grupo Random-PT
Olá! Na última palestra, conhecemos pela primeira vez o mecanismo integrado da linguagem Java - o coletor de lixo. Ele opera em segundo plano enquanto o programa está em execução, coletando objetos que se tornaram desnecessários, que posteriormente serão excluídos. Dessa forma, libera memória para a criação de novos objetos no futuro. Nesta palestra veremos mais de perto o princípio de seu funcionamento. Por exemplo, como e em que ponto um objeto se torna desnecessário? E como o coletor de lixo sabe disso? Responderemos a essas perguntas :) Nossa palestra é mais uma visão geral: este material não precisa ser memorizado. Pretende-se ampliar seus horizontes em relação ao trabalho da memória e do coletor de lixo, então bastará lê-lo e aprender algo novo para você :) Vamos lá! A primeira coisa que você precisa lembrar é que o coletor de lixo é executado em paralelo com o seu programa . Não faz parte e funciona separadamente: para descrever isso, na última palestra fizemos uma analogia com um aspirador robô. Na verdade, nem sempre foi assim. Anteriormente, o coletor de lixo era projetado de forma que funcionasse na mesma thread do seu programa. E de acordo com algum cronograma, a cada poucos minutos, ele começou a verificar a presença de objetos desnecessários no programa. O problema era que durante essa verificação e coleta de lixo o programa travou e não foi executado. Imagine que você está sentado em um escritório trabalhando. Mas aí chega uma faxineira e precisa lavar o chão do quarto. Ela te expulsa de trás do computador por 5 minutos e você espera até que ela termine de limpar. Durante esse período você não poderá trabalhar. Era mais ou menos assim que os coletores de lixo funcionavam :) Mais tarde, esse mecanismo foi alterado, e agora o coletor de lixo funciona em segundo plano, sem retardar o trabalho do próprio programa. Você já sabe que um objeto morre quando não há mais referências a ele. Mas o coletor de lixo na verdade não conta referências a arquivos . Em primeiro lugar, pode ser bastante longo. Em segundo lugar, não é muito eficaz. Afinal, os objetos podem referir-se uns aos outros! Mais sobre o coletor de lixo - 2A figura mostra um exemplo onde 3 objetos fazem referência entre si, mas ninguém mais faz referência a eles. Ou seja, eles não são necessários para que o restante do programa funcione. Se o coletor de lixo estivesse simplesmente contando referências, todos esses 3 objetos permaneceriam e não liberariam memória: existem referências a eles! Pode ser comparado a uma nave espacial. Durante o vôo, os astronautas resolveram verificar a lista de peças de reposição para reparos e encontraram entre elas um volante e pedais de um carro comum. Eles claramente não são necessários aqui e ocupam espaço extra. Embora essas peças estejam conectadas e tenham algumas funções, no âmbito da operação da espaçonave elas são lixo desnecessário, do qual é melhor se livrar. Portanto, Java decidiu fazer a base para a coleta de lixo não contando referências, mas dividindo os objetos em dois tipos - alcançáveis ​​e inacessíveis. Como determinar se um objeto é acessível? Tudo que é engenhoso é simples. Um objeto é alcançável se for referenciado por outro objeto alcançável. Isso resulta em uma “cadeia de acessibilidade”. Ele começa quando o programa é iniciado e continua durante toda a sua operação. É mais ou menos assim: Mais sobre o coletor de lixo - 4A seta na figura indica o código em execução do nosso programa. No código, por exemplo no método main(), são criadas referências a objetos. Esses objetos podem referir-se a novos objetos, outros a mais e assim por diante. Uma cadeia de links de objetos é formada . Se um objeto puder ser alcançado através desta cadeia de links até um “link raiz”, ou seja, um que seja criado diretamente no código em execução, ele será considerado alcançável. Na nossa foto eles estão indicados em azul. Mas se um objeto saiu dessa cadeia, ou seja, nenhuma das variáveis ​​​​do código em execução contém referências a ele, e também é impossível alcançá-lo através da “cadeia de links” - ele é considerado inacessível. Em nosso programa, dois desses objetos são indicados em vermelho. Observação: esses objetos “vermelhos” possuem links entre si. Mas, como dissemos anteriormente, o coletor de lixo moderno em Java não faz contagem de referências. Ele determina se um objeto é alcançável ou inacessível . Portanto, os dois objetos vermelhos da imagem se tornarão suas presas. Agora vamos dar uma olhada em todo o processo do início ao fim e, ao mesmo tempo, ver como funciona a memória em Java :) Todos os objetos em Java são armazenados em uma área de memória especial chamada heap . Na linguagem comum, uma “pilha” é uma montanha de objetos onde tudo está confuso. Mas o heap em Java não é assim. Tem uma estrutura muito lógica e razoável. Um belo dia, os programadores Java descobriram que todos os objetos em seus programas podem ser divididos em dois tipos - relativamente falando, objetos simples e objetos de “vida longa” . Objetos de “vida longa” são aqueles que sobreviveram a muitas coletas de lixo. Na maioria das vezes eles existirão até o final do programa. Como resultado, o heap comum, onde são armazenados todos os objetos criados, foi dividido em várias partes. A primeira parte tem um lindo nome - Eden (bíblico “Jardim do Éden”). Este é um ótimo nome porque é para onde os objetos vão depois de criados. É nesta parte que a memória é alocada para novos objetos quando escrevemosnew. Muitos objetos podem ser criados e, quando o espaço acabar nesta área, começa a primeira e “rápida” coleta de lixo. É preciso dizer que o coletor de lixo é muito inteligente e escolhe um algoritmo de trabalho dependendo do que há mais na pilha - lixo ou objetos de trabalho. Se quase todos os objetos forem lixo, o coletor marca os objetos “vivos” e os move para outra área de memória, após o que a área atual é completamente limpa. Se houver pouco lixo e a maior parte estiver ocupada por objetos vivos, ele marca o lixo, limpa e arruma os objetos restantes. Dissemos “o colecionador marca os objetos “vivos” e os move para outro local de memória”, mas qual? A área de memória para onde são transferidos todos os objetos que sobrevivem a pelo menos uma coleta de lixo é chamada de Espaço de Sobrevivência . O Espaço de Sobrevivência, por sua vez, é dividido em gerações . Cada objeto recebe uma geração com base em quantas coletas de lixo ele sofreu. Se houver, pertence à “Geração 1”, se 5 – à “Geração 5”. Juntos, Eden e Survival Space formam uma área chamada Young Generation . Além da Young Generation, há outra área de memória na pilha - Old Generation (“velha geração”). Esses são os objetos de vida muito longa que sobreviveram a muitas coletas de lixo. É mais lucrativo armazená-los separadamente de todos os outros. E somente quando a área da Velha Geração estiver cheia, ou seja. Mesmo que haja tantos objetos de longa duração no programa que não haja memória suficiente, uma coleta de lixo completa é executada. Ele processa não apenas uma área de memória, mas geralmente todos os objetos criados pela máquina Java. Naturalmente, é preciso muito mais tempo e recursos. É por isso que foi decidido armazenar separadamente os objetos de longa vida. Quando esgota o espaço em outras áreas, é realizada a chamada “coleta rápida de lixo”. Abrange apenas uma área e por isso é mais econômico e rápido. No final, quando até a área dos centenários já está lotada, entra na briga a limpeza completa. Assim, a ferramenta mais “pesada” é utilizada pelo montador apenas quando não é mais necessária. Esquematicamente, a estrutura da pilha e da limpeza é assim: Mais sobre o coletor de lixo - 5
Comentários
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION