Tengo una duda con la recolección de basura (Garbage Collector)

Iniciado por DarkSorcerer, 18 Enero 2013, 04:30 AM

0 Miembros y 1 Visitante están viendo este tema.

DarkSorcerer

Investigando por ahi, me di cuenta que Java elimina automaticamente variables primitivas (como int, long, float, etc) y de referencia, pero tambien me di cuenta que System tiene un metodo que ejecuta el recolector de basura, teniendo en cuenta eso, quise hacer un pequeño programa para ponerlo a prueba, se trata de una clase que se llama Empleado que guarda la información de un empleado, ademas de una variable static para ir contando los empleados que tiene la compañia, la cosa es que creo 2 empleados e imprimo los datos por pantalla, ademas de la cantidad de empleados y me salen que son 2, pero cuando al segundo empleado lo convierto en null y llamo al recolector de basura, no me lo borra de la memoria, y sigue marcando como 2 empleados en la compañia en vez de 1, ¿alguien sabe a que se debe esto?, ¿ que no se suponia que el recolector borra de la memoria las variables que son "inutiles"?

Les dejo el codigo

//Clase Empleado

package ejercicio83;

public class Empleado {
   
   private String nombre;
   private String rut;
   private int edad;
   private int sueldo;
   private static int cantEmpleados = 0;
   
   public Empleado(String nombre, String rut, int edad, int sueldo){
       
       this.nombre = nombre;
       this.rut = rut;
       this.edad = edad;
       this.sueldo = sueldo;
       this.cantEmpleados++;
       
   }
   
   public String getNombre(){
       
       return nombre;
       
   }
   
   public String getRut(){
       
       return rut;
       
   }
   
   public int getEdad(){
       
       return edad;
       
   }
   
   public int getSueldo(){
       
       return sueldo;
       
   }
   
   public static int getContratados(){
       
       return cantEmpleados;
       
   }
   
}


//Main

package ejercicio83;

public class Ejercicio83 {

    public static void main(String[] args) {
       
        Empleado empleado1 = new Empleado("Juan", "1234", 22 , 350000);
        Empleado empleado2 = new Empleado("Carlos", "5678", 30, 1200000);
       
        System.out.printf("\n\nNombre: %s\nRut: %s\nEdad: %d\nSueldo: %d", empleado1.getNombre(), empleado1.getRut(), empleado1.getEdad(), empleado1.getSueldo());
        System.out.printf("\n\nNombre: %s\nRut: %s\nEdad: %d\nSueldo: %d", empleado2.getNombre(), empleado2.getRut(), empleado2.getEdad(), empleado2.getSueldo());
       
        empleado2 = null;
        System.gc();
        System.out.printf("\n\n%d empleados\n", Empleado.getContratados());
       
    }
}


Nasty35

Primero, si la variable es estática no la puedes llamar como this.
Y te pasa porque borras una variable que contiene un objeto de la clase, pero como el valor cantEmpleados es estático, no puedes borrarlo de esa forma, tienes que hacer un algoritmo para que detecte cuando se valla un empleado y lo reste (cantEmpleados--), no sé si me entiendes... si es estático siempre es el mismo, y no lo puedes manejar individualmente por cada objeto de la clase.
pd: Si lo igualas a null, creo que automáticamente se recicla, y no hace falta llamar al GC.

Gallu

Hola , primero que nada debes tener claro que nada garantiza que el Garbage Collector se ejecute cuando tu le llamas a  System.gc();, con lo cual basta con que simplemente pongas la variable a null y listo.

Segundo, como quieres que el GC sepa que al eliminar el objeto debe restarlo del contador de tu clase, el GC no sabe que tu estas contando referencias .... lo que has de hacer es usar el método finalize, que es llamado antes de destruir un objeto , allí es donde agregarás el código que resta a tu contador. He modificado tu código con lo que te comento , ejecutalo y verás ...


Código (java) [Seleccionar]



class Empleado {
   
    private String nombre;
    private String rut;
    private int edad;
    private int sueldo;
    private static int cantEmpleados = 0;
   
    public Empleado(String nombre, String rut, int edad, int sueldo){
       
        this.nombre = nombre;
        this.rut = rut;
        this.edad = edad;
        this.sueldo = sueldo;
        Empleado.cantEmpleados++;
       
    }
   
    public String getNombre(){
       
        return nombre;
       
    }
   
    public String getRut(){
       
        return rut;
       
    }
   
    public int getEdad(){
       
        return edad;
       
    }
   
    public int getSueldo(){
       
        return sueldo;
       
    }
   
    public static int getContratados(){
       
        return cantEmpleados;
       
    }
    //resta uno al contador de objetos
    protected void finalize(){
Empleado.cantEmpleados--;
    }
   
}




public class Ejercicio83 {

    public static void main(String[] args) {
       
        Empleado empleado1 = new Empleado("Juan", "1234", 22 , 350000);
        Empleado empleado2 = new Empleado("Carlos", "5678", 30, 1200000);
       
        System.out.printf("\n\nNombre: %s\nRut: %s\nEdad: %d\nSueldo: %d", empleado1.getNombre(), empleado1.getRut(), empleado1.getEdad(), empleado1.getSueldo());
        System.out.printf("\n\nNombre: %s\nRut: %s\nEdad: %d\nSueldo: %d", empleado2.getNombre(), empleado2.getRut(), empleado2.getEdad(), empleado2.getSueldo());
       
        empleado2 = null;
boolean objetoEliminado = false;
while(!objetoEliminado){
if(Empleado.getContratados() == 1){
objetoEliminado = true;
}
}
        System.out.printf("\n\n%d empleados\n", Empleado.getContratados());
       
    }
}


Espero haber sido claro.

Saludos
Nadie alcanza la meta con un solo intento, ni perfecciona la vida con una sola rectificación, ni alcanza altura con un solo vuelo.