CodeGym /Blog Java /Random-ES /Ciclo de vida del objeto
Autor
John Selawsky
Senior Java Developer and Tutor at LearningTree

Ciclo de vida del objeto

Publicado en el grupo Random-ES
¡Hola! Creo que no te sorprendería mucho si te dijera que tu computadora tiene una cantidad limitada de memoria :)
Ciclo de vida del objeto - 1
Incluso su disco duro (que es muchas, muchas veces el tamaño de la RAM) puede llenarse hasta los topes de sus juegos favoritos, programas de TV y otras cosas. Para evitar que esto suceda, debe controlar el estado actual de la memoria de su computadora y eliminar los archivos innecesarios. ¿Cómo se relaciona todo esto con la programación en Java? ¡Muy directamente! Después de todo, la creación de cualquier objeto hace que la máquina Java le asigne memoria . Un gran programa del mundo real crea decenas o cientos de miles de objetos, y se asigna una parte de la memoria para cada uno de ellos. Pero qué opinas, ¿cuántos de estos objetos existen? ¿Están "vivos" todo el tiempo mientras se ejecuta nuestro programa? Por supuesto que no. Incluso con todas sus ventajas, los objetos de Java no son inmortales :) Los objetos tienen su propio ciclo de vida. Hoy tomaremos un pequeño descanso de escribir código y exploraremos este proceso :) También es muy importante para comprender cómo funciona un programa y para administrar los recursos. Entonces, ¿dónde comienza la vida de un objeto? Como un ser humano, desde que nace, es decir, cuando es creado.

Cat cat = new Cat();// Our Cat object's lifecycle begins now!
Primero, la máquina virtual Java asigna la memoria necesaria para crear el objeto. Luego crea una referencia a él (en nuestro caso, cat) para que sea posible realizar un seguimiento de él. Luego, todas las variables se inicializan, se llama al constructor y nuestro nuevo objeto ahora está viviendo su propia vida :) La duración de los objetos varía. No hay cifras exactas aquí. En cualquier caso, un objeto vive en el programa y realiza sus funciones durante un período de tiempo. Para ser precisos, el objeto está "vivo" mientras haya referencias a él. Tan pronto como no hay referencias, el objeto "muere". Por ejemplo:

public class Car {
  
   String model;

   public Car(String model) {
       this.model = model;
   }

   public static void main(String[] args) {
       Car lamborghini  = new Car("Lamborghini Diablo");
       lamborghini = null;

   }

}
En el main()método, el objeto Coche "Lamborghini Diablo" deja de estar vivo en la segunda línea. Solo había una referencia a él, y la referencia se estableció en nulo. Como no quedan referencias al Diablo, se convierte en "basura". Una referencia no tiene que establecerse en cero para que esto suceda:

public class Car {

   String model;

   public Car(String model) {
       this.model = model;
   }

   public static void main(String[] args) {
       Car lamborghini  = new Car("Lamborghini Diablo");

       Car lamborghiniGallardo = new Car("Lamborghini Gallardo");
       lamborghini = lamborghiniGallardo;
   }

}
Aquí hemos creado un segundo objeto y lo asignamos a la referencia de lamborghini. Ahora dos referencias apuntan al Lamborghini Gallardoobjeto, pero el Lamborghini Diabloobjeto no tiene ninguna. Esto significa que el Diabloobjeto se convierte en basura. Aquí es cuando se activa el recolector de basura (GC) integrado de Java .
Ciclo de vida del objeto - 2
El recolector de basura es un mecanismo interno de Java responsable de liberar memoria, es decir, eliminar objetos innecesarios de la memoria. Hay una razón por la que elegimos representarlo con una aspiradora robot. El recolector de basura funciona más o menos de la misma manera: "se mueve" por su programa en segundo plano, recogiendo basura. Prácticamente no tienes que interactuar con él. Su trabajo es eliminar objetos que ya no se utilizan en el programa. Por lo tanto, libera memoria para otros objetos. ¿Recuerdas que al comienzo de la lección dijimos que en la vida real tienes que monitorear el estado de tu computadora y eliminar los archivos antiguos? Si estamos hablando de objetos Java, el recolector de basura hace esto por ti. El recolector de elementos no utilizados se inicia muchas veces a medida que se ejecuta el programa: no tiene que llamarlo explícitamente y darle comandos (aunque esto es técnicamente posible). Hablaremos más sobre el recolector de basura más adelante y analizaremos cómo funciona con más detalle. Cuando el recolector de basura llega a un objeto, justo antes de que se destruya, finalize()se llama al método especial del objeto. Este método se puede invocar para liberar ciertos recursos adicionales utilizados por el objeto. El finalize()método pertenece a la clase Object. En otras palabras, es similar a equals(), hashCode()y toString()(que ya conoces). Todo objeto lo tiene . Se diferencia de otros métodos en que... ¿cómo deberíamos decir esto?... es muy intencional. Con eso queremos decir queno siempre se llama antes de que se destruya un objeto . La programación es una actividad muy precisa. El programador le dice a la computadora que haga algo, y la computadora lo hace. Supongo que se ha acostumbrado a este tipo de comportamiento, por lo que al principio puede resultarle difícil aceptar la siguiente idea: "Antes de que se destruya un objeto, se llama al método de la clase Object. O no. ¡Si tenemos suerte finalize()! " Aún así, esta es la realidad. La propia máquina Java determina si llamar a finalize() caso por caso. Como experimento, intentemos ejecutar el siguiente código:

public class Cat {

   private String name;

   public Cat(String name) {
       this.name = name;
   }

   public Cat() {
   }

   public static void main(String[] args) throws Throwable {

       for (int i = 0 ; i < 1000000; i++) {

           Cat cat = new Cat();
           cat = null;// The first object becomes available for garbage collection here
       }
   }

   @Override
   protected void finalize() throws Throwable {
       System.out.println("The Cat is destroyed!");
   }
}
Creamos un Catobjeto, y en la siguiente línea ponemos a cero la única referencia a él. Y lo hacemos un millón de veces. Hemos invalidado explícitamente el finalize()método. Cada vez que Catse destruye un objeto, debe mostrar una cadena, un total de un millón de veces. ¡Pero no! ¡Para ser exactos, en mi computadora se ejecutó solo 37346 veces! En otras palabras, mi máquina Java decidió llamar al finalize()método solo en 1 de cada 27 casos. En los otros casos, la recolección de basura no involucró esta llamada. Intente ejecutar este código usted mismo. Lo más probable es que obtenga un resultado diferente. Como puede ver, es difícil llamar finalize()a un socio confiable :) Entonces, aquí hay un pequeño consejo para el futuro: no confíe en el finalize()método para liberar recursos críticos.La JVM podría llamarlo, o podría no hacerlo. ¿Quién sabe? Si su objeto contenía algunos recursos críticos para el rendimiento (por ejemplo, una conexión de base de datos abierta) mientras estaba activo, sería mejor crear y llamar explícitamente a un método especial para liberarlos cuando el objeto ya no sea necesario. De esa manera, sabrá con certeza que el rendimiento de su programa no se verá afectado. Comenzamos diciendo que trabajar con la memoria y la recolección de basura son temas muy importantes, y de hecho lo son. El mal manejo de los recursos y la mala comprensión de cómo se limpian los objetos innecesarios pueden conducir a uno de los errores más desagradables: las fugas de memoria . Este es uno de los errores de programación más conocidos. Incluso tiene su propio artículo de Wikipedia.. El código mal escrito puede crear una situación en la que se asigna memoria cada vez para objetos recién creados, pero los objetos viejos e innecesarios no están disponibles para la recolección de elementos no utilizados. Como ya hemos hecho la analogía del robot aspirador, imagina lo que sucedería si antes de ejecutar el robot esparcieras calcetines por toda la casa, rompieras un jarrón de vidrio y dejaras piezas de Lego por todo el piso. Naturalmente, el robot intentará hacer algo, pero un día se atascará.
Ciclo de vida del objeto - 3
Para que la aspiradora funcione correctamente, debe mantener el piso en buen estado y recoger todo lo que no puede manejar. El recolector de basura sigue el mismo principio. Si un programa tiene muchos objetos que no puede limpiar (como un calcetín o Lego para nuestra aspiradora robótica), un día nos quedaremos sin memoria. No solo se bloqueará su programa, sino que también lo harán todos los demás programas que se estén ejecutando en la computadora. Después de todo, tampoco tendrán suficiente memoria (volviendo a nuestra analogía, el vidrio roto en el piso detiene no solo a la aspiradora, sino también a las personas que viven en el hogar). En resumen, así es como se ve el ciclo de vida de los objetos y la recolección de basura en Java. No necesitas memorizar esto: es suficiente simplemente entender cómo funciona. En la próxima lección, Volveré a estos procesos con más detalle. Pero por ahora, puedes volver a resolver las tareas de CodeGym :) ¡Buena suerte!
Comentarios
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION