Recolección de basura en Java

La recolección de basura en Java es el proceso mediante el cual los programas Java realizan la gestión automática de la memoria. Los programas de Java se compilan en un código de bytes que se puede ejecutar en una máquina virtual de Java, o JVM para abreviar. Cuando los programas Java se ejecutan en la JVM, los objetos se crean en el montón, que es una parte de la memoria dedicada al programa. Eventualmente, algunos objetos ya no serán necesarios. El recolector de elementos no utilizados encuentra estos objetos no utilizados y los elimina para liberar memoria.

¿Qué es la recolección de basura?

En C/C++, un programador es responsable tanto de la creación como de la destrucción de objetos. Por lo general, el programador descuida la destrucción de objetos inútiles. Debido a esta negligencia, en cierto punto, es posible que no haya suficiente memoria disponible para crear nuevos objetos, y todo el programa terminará de manera anormal, causando OutOfMemoryErrors .

Pero en Java, el programador no necesita preocuparse por todos aquellos objetos que ya no están en uso. El recolector de basura destruye estos objetos. El principal objetivo de Garbage Collector es liberar memoria del montón destruyendo objetos inalcanzables . El recolector de basura es el mejor ejemplo del subproceso Daemon , ya que siempre se ejecuta en segundo plano. 

¿Cómo funciona la recolección de basura en Java?

La recolección de elementos no utilizados de Java es un proceso automático. La recolección automática de elementos no utilizados es el proceso de observar la memoria del montón, identificar qué objetos están en uso y cuáles no, y eliminar los objetos no utilizados. Un objeto en uso, o un objeto al que se hace referencia, significa que alguna parte de su programa aún mantiene un puntero a ese objeto. Un objeto no utilizado o sin referencia ya no es referenciado por ninguna parte de su programa. Entonces, la memoria utilizada por un objeto sin referencia puede recuperarse. El programador no necesita marcar los objetos para que se eliminen explícitamente. La implementación de la recolección de basura vive en la JVM. 

Tipos de actividades en la recolección de basura de Java

Dos tipos de actividad de recolección de basura generalmente ocurren en Java. Estos son:

  1. Recolección de basura menor o incremental: se dice que ocurrió cuando se eliminaron objetos inalcanzables en la memoria del montón de generación joven.
  2. Recolección de basura mayor o completa: se dice que ocurrió cuando los objetos que sobrevivieron a la recolección de basura menor se copian en la memoria de almacenamiento dinámico de generación anterior o permanente y se eliminan. En comparación con la generación joven, la recolección de basura ocurre con menos frecuencia en la generación anterior.

Conceptos importantes relacionados con la recolección de basura en Java

1. Objetos inalcanzables: se dice que un objeto es inalcanzable si no contiene ninguna referencia a él. Además, tenga en cuenta que los objetos que forman parte de la isla de aislamiento también son inalcanzables. 

Integer i = new Integer(4);
// the new Integer object is reachable  via the reference in 'i' 
i = null;
// the Integer object is no longer reachable. 

garbage collection

2. Elegibilidad para recolección de basura: se dice que un objeto es elegible para GC (recolección de basura) si es inalcanzable. Después de i = null , el objeto entero 4 en el área del montón es adecuado para la recolección de basura en la imagen de arriba.

Maneras de hacer que un objeto sea elegible para Garbage Collector

  • Aunque el programador no es responsable de destruir objetos inútiles, se recomienda encarecidamente hacer que un objeto sea inalcanzable (por lo tanto, elegible para GC) si ya no es necesario.
  • En general, hay cuatro formas de hacer que un objeto sea apto para la recolección de elementos no utilizados.
    1. Anular la variable de referencia
    2. Reasignación de la variable de referencia
    3. Un objeto creado dentro del método.
    4. isla de aislamiento

Formas de solicitar a JVM que ejecute Garbage Collector

  • Una vez que hacemos que un objeto sea elegible para la recolección de basura, es posible que el recolector de basura no lo destruya inmediatamente. Siempre que JVM ejecute el programa Garbage Collector, solo se destruirá el objeto. Pero cuando JVM ejecuta Garbage Collector, no podemos esperar.
  • También podemos solicitar a JVM que ejecute Garbage Collector. Hay dos maneras de hacerlo : 
    1. Uso del método System.gc() : la clase del sistema contiene el método estático gc() para solicitar a JVM que ejecute Garbage Collector.
    2. Uso del método Runtime.getRuntime().gc() : la clase de tiempo de ejecución permite que la aplicación interactúe con la JVM en la que se ejecuta la aplicación. Por lo tanto, al usar su método gc(), podemos solicitar a JVM que ejecute Garbage Collector.
    3. No hay garantía de que cualquiera de los dos métodos anteriores ejecute Garbage Collector.
    4. La llamada System.gc() es efectivamente equivalente a la llamada: Runtime.getRuntime().gc()

finalización

  • Justo antes de destruir un objeto, Garbage Collector llama al método finalize() en el objeto para realizar actividades de limpieza. Una vez que se completa el método finalize() , Garbage Collector destruye ese objeto.
  • El método finalize() está presente en la clase Object con el siguiente prototipo.
protected void finalize() throws Throwable

Según nuestro requisito, podemos anular el método finalize() para realizar nuestras actividades de limpieza, como cerrar la conexión desde la base de datos. 

  1. El método finalize() es llamado por Garbage Collector, no por JVM. Sin embargo, Garbage Collector es uno de los módulos de JVM.
  2. El método finalize() de la clase de objeto tiene una implementación vacía. Por lo tanto, se recomienda anular el método finalize() para deshacerse de los recursos del sistema o realizar otras limpiezas.
  3. El método finalize() nunca se invoca más de una vez para cualquier objeto.
  4. Si el método finalize() lanza una excepción no detectada , la excepción se ignora y finaliza la finalización de ese objeto.

Ventajas de la recolección de basura en Java

Las ventajas de Garbage Collection en Java son:

  • Hace que la memoria de Java sea eficiente porque el recolector de basura elimina los objetos sin referencia de la memoria del montón.
  • El recolector de basura (una parte de JVM) lo hace automáticamente, por lo que no necesitamos un esfuerzo adicional.

Ejemplo del mundo real

Tomemos un ejemplo de la vida real, donde usamos el concepto del recolector de basura.

Pregunta: Suponga que realiza una pasantía en GeeksForGeeks y le piden que escriba un programa para contar la cantidad de empleados que trabajan en la empresa (excluyendo los pasantes). Para hacer este programa, tienes que usar el concepto de un recolector de basura. 

Esta es la tarea real que le dieron en la empresa:

Escriba un programa para crear una clase llamada Empleado que tenga los siguientes miembros de datos. 

1. Una identificación para almacenar una identificación única asignada a cada empleado. 
2. Nombre del empleado. 
3. edad de un empleado.

Además, proporcione los siguientes métodos:

  1. Un constructor parametrizado para inicializar el nombre y la edad. El ID debe inicializarse en este constructor.
  2. Un método show() para mostrar ID, nombre y edad.
  3. Un método showNextId() para mostrar la identificación del próximo empleado.

Ahora, cualquier principiante que no conozca Garbage Collector en Java codificará así: 

Java

// Java Program to count number
// of employees working
// in a company
 
class Employee {
   
    private int ID;
    private String name;
    private int age;
    private static int nextId = 1;
    // it is made static because it
    // is keep common among all and
    // shared by all objects
   
    public Employee(String name, int age)
    {
        this.name = name;
        this.age = age;
        this.ID = nextId++;
    }
    public void show()
    {
        System.out.println("Id=" + ID + "\nName=" + name
                           + "\nAge=" + age);
    }
    public void showNextId()
    {
        System.out.println("Next employee id will be="
                           + nextId);
    }
}
 
class UseEmployee {
    public static void main(String[] args)
    {
        Employee E = new Employee("GFG1", 56);
        Employee F = new Employee("GFG2", 45);
        Employee G = new Employee("GFG3", 25);
        E.show();
        F.show();
        G.show();
        E.showNextId();
        F.showNextId();
        G.showNextId();
 
        { // It is sub block to keep
            // all those interns.
            Employee X = new Employee("GFG4", 23);
            Employee Y = new Employee("GFG5", 21);
            X.show();
            Y.show();
            X.showNextId();
            Y.showNextId();
        }
        // After countering this brace, X and Y
        // will be removed.Therefore,
        // now it should show nextId as 4.
           
          // Output of this line
        E.showNextId();
        // should be 4 but it will give 6 as output.
    }
}
Producción

Id=1
Name=GFG1
Age=56
Id=2
Name=GFG2
Age=45
Id=3
Name=GFG3
Age=25
Next employee id will be=4
Next employee id will be=4
Next employee id will be=4
Id=4
Name=GFG4
Age=23
Id=5
Name=GFG5
Age=21
Next employee id will be=6
Next employee id will be=6
Next employee id will be=6

Ahora, para obtener el resultado correcto: 
ahora el recolector de basura (gc) verá 2 objetos gratis. Ahora, para disminuir nextId, gc (recolector de basura) llamará al método para finalizar() solo cuando los programadores lo hayamos anulado en nuestra clase. Y como se mencionó anteriormente, debemos solicitar gc (recolector de basura), y para esto, debemos escribir los siguientes 3 pasos antes de cerrar la llave del subbloque.  

  1. Establecer referencias en nulo (es decir, X = Y = nulo;)
  2. Llamada, Sistema.gc();
  3. Llamada, System.runFinalization();

Ahora el código correcto para contar el número de empleados (excluyendo pasantes)  

Java

// Correct code to count number
// of employees excluding interns.
 
class Employee {
   
    private int ID;
    private String name;
    private int age;
    private static int nextId = 1;
   
    // it is made static because it
    // is keep common among all and
    // shared by all objects
    public Employee(String name, int age)
    {
        this.name = name;
        this.age = age;
        this.ID = nextId++;
    }
    public void show()
    {
        System.out.println("Id=" + ID + "\nName=" + name
                           + "\nAge=" + age);
    }
    public void showNextId()
    {
        System.out.println("Next employee id will be="
                           + nextId);
    }
    protected void finalize()
    {
        --nextId;
        // In this case,
        // gc will call finalize()
        // for 2 times for 2 objects.
    }
}
 
public class UseEmployee {
    public static void main(String[] args)
    {
        Employee E = new Employee("GFG1", 56);
        Employee F = new Employee("GFG2", 45);
        Employee G = new Employee("GFG3", 25);
        E.show();
        F.show();
        G.show();
        E.showNextId();
        F.showNextId();
        G.showNextId();
 
        {
            // It is sub block to keep
            // all those interns.
            Employee X = new Employee("GFG4", 23);
            Employee Y = new Employee("GFG5", 21);
            X.show();
            Y.show();
            X.showNextId();
            Y.showNextId();
            X = Y = null;
            System.gc();
            System.runFinalization();
        }
        E.showNextId();
    }
}

Producción

Id=1
Name=GFG1
Age=56
Id=2
Name=GFG2
Age=45
Id=3
Name=GFG3
Age=25
Next employee id will be=4
Next employee id will be=4
Next employee id will be=4
Id=4
Name=GFG4
Age=23
Id=5
Name=GFG5
Age=21
Next employee id will be=6
Next employee id will be=6
Next employee id will be=4

Artículos relacionados:  

Este artículo es una contribución de Chirag Agarwal y Gaurav Miglani . Escriba comentarios si encuentra algo incorrecto o si desea compartir más información sobre el tema tratado anteriormente.

Publicación traducida automáticamente

Artículo escrito por GeeksforGeeks-1 y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *