Article image
Michel Matos
Michel Matos19/12/2023 10:10
Compartilhe

C# /.NET - Garbage Collection

  • #.NET C#

O Garbage Collection (Coleta de Lixo) é um processo automatizado presente em linguagens de programação modernas, como C#, Java, Python, entre outras. Seu objetivo é gerenciar a alocação e desalocação de memória de forma automática, liberando a memória que não está mais sendo utilizada pelo programa, ou seja, os objetos que não têm mais referências para eles.

Na vida real:

Imagine que você está morando em uma casa e ao longo do tempo você adquire várias coisas, como móveis, roupas, livros, utensílios domésticos, etc. Você usa esses itens conforme sua necessidade, mas eventualmente alguns itens se tornam desnecessários ou você simplesmente não precisa mais deles.

Na sua casa, você tem um serviço de coleta de lixo automática que verifica periodicamente quais objetos ou itens não estão mais sendo usados ou não têm um propósito atual. Por exemplo, roupas que você não veste há anos, livros que você já leu e não pretende reler, ou móveis que foram substituídos por versões mais novas.

Assim como no Garbage Collection, onde o sistema identifica objetos não referenciados, nessa analogia, o serviço de coleta de lixo em sua casa identifica esses itens que não estão mais em uso ou não têm mais importância para você. Quando a coleta de lixo é realizada, esses itens são marcados para serem retirados e alocados para outras finalidades (como reciclagem, doação, etc.).

Da mesma forma, no desenvolvimento de software em C# (ou outras linguagens com GC), o Garbage Collector atua como esse serviço de coleta de lixo em sua casa, identificando objetos (ou "itens" na analogia) que não são mais necessários e os removendo da memória, liberando espaço para novos objetos.

Na vida do C#:

No C#, o Garbage Collector (Coletor de Lixo) utiliza um algoritmo complexo para identificar os objetos que não estão mais sendo referenciados e, portanto, podem ser considerados lixo para serem coletados. Ele não segue uma periodicidade fixa, como a cada X segundos ou minutos. Em vez disso, sua execução é gerenciada pelo Common Language Runtime (CLR) da Microsoft, que decide quando acionar o Garbage Collector.

O Garbage Collector é ativado de forma dinâmica com base em certos critérios e condições. Alguns desses critérios incluem:

  1. Geração de Objetos: O Garbage Collector no .NET Framework (e .NET Core) trabalha com diferentes gerações de objetos (0, 1 e 2). Ele coleta principalmente objetos nas gerações mais novas (0 e 1) com mais frequência, já que objetos recentemente alocados têm uma alta taxa de mortalidade, ou seja, são mais propensos a se tornarem lixo.
  2. Pressão sobre a Memória: Quando a aplicação está com pouca memória disponível, o CLR pode decidir acionar o Garbage Collector para liberar espaço e evitar uma exceção de falta de memória (OutOfMemoryException).
  3. Tempo de Execução e Alocação de Memória: O Garbage Collector é acionado durante a execução do programa, e a alocação contínua de novos objetos pode acionar a ativação do Garbage Collector em momentos oportunos.
  4. Gen0, Gen1, Gen2: A coleta de lixo acontece em diferentes gerações de objetos, com frequência variável para cada uma. Objetos de curta duração são frequentemente coletados na geração 0, enquanto objetos de média e longa duração passam para gerações subsequentes.
  5. GC.Collect(): Embora não seja recomendado em situações normais, é possível invocar explicitamente a coleta de lixo por meio do método GC.Collect(). Isso força a execução do Garbage Collector, mas a decisão final de quando e quais objetos coletar ainda é determinada pelo CLR.

Na vida do código:

using System;

class Program
{
 static void Main()
 {
     // Criação de objetos
     Pessoa pessoa1 = new Pessoa("João"); // Objeto 1
     Pessoa pessoa2 = new Pessoa("Maria"); // Objeto 2

     // Atribuindo a pessoa2 para pessoa1
     pessoa1 = pessoa2; // O objeto 1 (anteriormente referenciado por pessoa1) não é mais acessível

     // Chamando o coletor de lixo explicitamente (apenas para fins ilustrativos)
     GC.Collect();

     Console.ReadLine(); // Aguarda pressionar Enter para finalizar
 }
}

class Pessoa
{
 public string Nome { get; set; }

 public Pessoa(string nome)
 {
     Nome = nome;
 }

 ~Pessoa()
 {
     Console.WriteLine($"Objeto Pessoa de {Nome} foi coletado pelo Garbage Collector.");
 }
}

Nesse exemplo, criamos uma classe Pessoa que tem um campo Nome e um construtor para inicializar esse campo. No método Main(), criamos dois objetos Pessoa (pessoa1 e pessoa2). Em seguida, atribuímos pessoa2 para pessoa1, o que faz com que o objeto original referenciado por pessoa1 não seja mais acessível.

Após isso, chamamos explicitamente GC.Collect() para acionar o Garbage Collector. É importante ressaltar que, na prática, normalmente não se chama manualmente o Garbage Collector, pois ele é executado automaticamente em momentos oportunos pelo tempo de execução (runtime).

Quando o Garbage Collector é invocado ou quando o programa termina, os objetos não referenciados são marcados para coleta e, eventualmente, desalocados da memória. No exemplo, dentro do destrutor (~Pessoa()), uma mensagem é exibida no console sempre que um objeto Pessoa é coletado pelo Garbage Collector.

Na vida do desenvolvedor:

No contexto de linguagens como C# e .NET, o Garbage Collection (Coleta de Lixo) não é uma classe implementada pelo programador, mas sim uma funcionalidade incorporada no tempo de execução (runtime) da plataforma .NET, como parte do Common Language Runtime (CLR). Não é necessário que os desenvolvedores implementem ou escrevam código específico para o Garbage Collection.

O Garbage Collection opera de maneira implícita, em segundo plano, sem a necessidade de intervenção direta por parte do desenvolvedor. Ele é responsável por gerenciar a alocação e liberação de memória de forma automática, identificando objetos que não estão mais sendo utilizados e liberando a memória ocupada por esses objetos.

Quando os desenvolvedores criam e utilizam objetos em um programa C#, eles simplesmente os utilizam normalmente sem se preocupar em desalocar explicitamente a memória alocada para esses objetos quando não são mais necessários. O Garbage Collector entra em ação, de forma automática e transparente, identificando os objetos que não têm mais referências válidas a partir do ponto de execução do programa (os chamados "objetos não mais referenciados") e então os remove da memória.

Essa abordagem do Garbage Collection permite que os desenvolvedores se concentrem na lógica de programação e na criação de seus aplicativos sem a preocupação constante de gerenciar manualmente a alocação e desalocação de memória, tornando o processo de desenvolvimento mais produtivo e reduzindo significativamente os riscos de vazamentos de memória e problemas relacionados à gestão manual de recursos.

Em linguagens que não possuem um sistema de garbage collection, os programadores são responsáveis por alocar memória para objetos e também por liberar essa memória quando esses objetos não são mais necessários. Esse gerenciamento manual pode levar a problemas como vazamento de memória (memory leaks) ou acesso a áreas de memória inválidas (como em casos de tentar acessar memória liberada).

E por fim...

É importante observar que, embora o Garbage Collector seja altamente eficiente na maioria dos casos, não é perfeito. Em situações extremamente sensíveis ao desempenho, pode ser necessário ajustar ou otimizar o código para gerenciar melhor a alocação de memória e minimizar a pressão sobre o Garbage Collector, embora isso geralmente não seja necessário em situações normais de desenvolvimento.

Fonte de estudo:

Documentação Microsoft sobre Garbage Collection - .NET

Compartilhe
Comentários (1)

RS

Romullo Silva - 19/12/2023 11:18

top!