ProgramaciónDesarrollador Java

¿Cómo funciona el mecanismo de gestión automática de memoria en Java (Garbage Collector)?

Supere entrevistas con el asistente de IA Hintsage

Respuesta

En Java, la gestión de la memoria se lleva a cabo mediante la recolección automática de basura (Garbage Collector, GC). La JVM rastrea automáticamente los objetos en memoria: si un objeto ya no tiene referencias, se vuelve inalcanzable y puede ser eliminado.

El GC consta de diferentes fases, como Mark, Sweep y a veces Compact. En la fase Mark, los objetos a los que se puede acceder desde las raíces (GC roots) se marcan como vivos. Después de esto, comienza la fase Sweep: los objetos no utilizados se eliminan. A veces se realiza Compact, que es la desfragmentación de la memoria.

Existen diferentes tipos de GC: Serial, Parallel, CMS, G1. Deben elegirse según el tipo de carga de trabajo de la aplicación.

Ejemplo de código — situación de fuga de memoria:
List<byte[]> dataList = new ArrayList<>(); while(true) { dataList.add(new byte[1024*1024]); // Los objetos permanecen alcanzables }

En este ejemplo, los objetos nunca se volverán inalcanzables, el GC no los eliminará y ocurrirá un OutOfMemoryError.

Pregunta capciosa

Si un objeto ya no tiene referencias, ¿cuándo se garantiza la llamada a su finalizador (finalize())?

Respuesta: ¡La llamada al método finalize() no está garantizada en absoluto! Puede no ser llamado en absoluto o con retraso. No se puede confiar en finalize() para liberar recursos.

@Override protected void finalize() throws Throwable { // ¡Puede que no se ejecute! }

Ejemplos de errores reales debido a la falta de conocimiento sobre los detalles del tema


Historia

En un sistema de e-commerce grande, los desarrolladores esperaban automatizar la limpieza de archivos temporales utilizando el método finalize(), pero debido a la rara invocación de este método, la caché se llenó de archivos temporales, lo que llevó a la falta de espacio en disco y paradas del sistema.


Historia

En una API REST de alta carga, se guardó accidentalmente una caché interna de referencias a grandes objetos, lo que impedía la liberación de memoria. Tras la caída de la aplicación con OutOfMemoryError, el análisis mostró un error en el método de caché.


Historia

Se utilizaban finalizadores para liberar conexiones de red, considerándolo un método confiable. Esto resultó en que las conexiones quedaban colgadas en el sistema indefinidamente, causando bloqueos y agotamiento del pool de conexiones.