Gestión de memoria en Kotlin: cómo funciona el recolector de basura

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

Memoria y recolector de basura en Kotlin: cómo no perder RAM ni rendimiento

\n\n

¿Alguna vez te has preguntado a dónde va la memoria RAM de tu aplicación en Kotlin? El código parece estar escrito perfectamente, las corrutinas vuelan, pero después de una hora de funcionamiento, el programa comienza a "ir lento" o falla con OutOfMemoryError. ¿Un dolor familiar? Bienvenido al club de aquellos que quieren entender cómo Kotlin gestiona la memoria y por qué el recolector de basura no es el enemigo, sino tu mejor amigo (si sabes cómo llevarte bien con él).

\n\n

En este artículo, nos sumergiremos en el tema de la gestión de memoria en Kotlin y analizaremos cómo funciona el recolector de basura en Kotlin en diferentes plataformas. Aprenderás qué son la pila y el montón, cómo evitar fugas y por qué WeakReference puede salvar tu proyecto. ¡Allá vamos!

\n\n

¿Qué es la memoria en Kotlin? Pila, montón y sus amigos

\n\n

Kotlin es un lenguaje multiplataforma. Se compila a bytecode de la JVM, a código nativo (a través de Kotlin/Native) o a JavaScript (Kotlin/JS). Y en cada plataforma, la memoria está organizada de manera ligeramente diferente, pero la base es la misma en todas.

\n\n

Recordemos los fundamentos. Cuando tu programa se inicia, el sistema operativo le asigna un área de memoria. Dentro de esta área hay dos "regiones" principales:

\n\n
    \n
  • Pila (Stack) — aquí se almacenan las variables locales, los primitivos y las referencias a objetos. Funciona como una pila de platos: rápido, predecible, pero con un tamaño limitado. Salirse de la pila provoca un StackOverflowError.
  • \n
  • Montón (Heap) — el vertedero para todos los objetos que creas mediante new o un constructor (val list = mutableListOf()). El montón es grande, pero lento, y es aquí donde "vive" el recolector de basura de Kotlin.
  • \n
\n\n

En la JVM, la pila y el montón funcionan de manera clásica. En Kotlin/Native, la pila es la pila nativa del hilo, y el montón es gestionado por su propio recolector de basura. En Kotlin/JS, todo recae sobre el motor de JavaScript (V8, SpiderMonkey).

\n\n

Punto clave: las referencias a objetos se almacenan en la pila, y los objetos mismos, en el montón. Mientras un objeto tenga al menos una referencia "viva" (desde la pila u otro objeto), el recolector de basura no lo tocará.

\n\n

Recolector de basura en Kotlin: cómo funciona en la JVM

\n\n

Cuando escribes en Kotlin para la JVM (Android, servidor), obtienes el poder del Recolector de Basura de la Máquina Virtual Java (GC). No es algo específico de Kotlin, pero es necesario entender su mecánica.

\n\n

La JVM moderna utiliza G1GC (Garbage First) o ZGC (en versiones nuevas). Así funciona de manera simplificada:

\n\n
    \n
  1. Mark (Marcado) — el GC "recorre" todos los objetos vivos, comenzando desde los puntos raíz (pila, campos estáticos). Todo lo que alcanza está vivo.
  2. \n
  3. Sweep (Barrido) — todo lo que no está marcado se considera basura y se elimina.
  4. \n
  5. Compact (Compactación) — los objetos vivos se desplazan para evitar la fragmentación.
  6. \n
\n\n

En G1GC, el montón está dividido en regiones. El GC recolecta aquellas regiones donde hay más basura (de ahí el nombre). Esto reduce las pausas, pero no las elimina por completo.

\n\n

En Kotlin, puedes influir en el recolector de basura a través de las banderas de la JVM (para servidores) o mediante GarbageCollectorMXBean (para monitoreo). Pero la mayoría de las veces, solo necesitas escribir código que no interfiera con el trabajo del GC.

\n\n

Ejemplo: cómo ve el GC tu código

\n\n
fun processData() {\n    val list = mutableListOf<String>()\n    for (i in 1..100_000) {\n        list.add("Element $i")\n    }\n    // Aquí list está vivo, hasta que el método termine\n    println(list.size)\n    // Después de salir del método, list se convierte en basura\n}\n
\n\n

Después de que processData() finaliza, la referencia a list desaparece de la pila, y el objeto se convierte en candidato para la recolección. Sencillo, ¿verdad?

\n\n

Particularidades de Kotlin/Native: recolector de basura sin JVM

\n\n

Ko

Blogs

Book Recommendations