1. Introducción al JVM
Cuando ejecutas un programa escrito en Java, obtienes un proceso de Java que consiste en el JVM y los bytecode que se ejecutan sobre él.
El JVM es la «máquina virtual Java», encargada de interpretar y ejecutar las instrucciones de Java.
2. Modelo de Memoria del JVM
2.1. Contador de Programa
Función: Almacena la dirección de la próxima instrucción a ejecutar.
Estas instrucciones son bytecode de Java, no código máquina binario del CPU.
2.2. Heap
La mayor parte del espacio en el JVM, donde se alojan todos los objetos creados con new.
2.3. Stack
Contiene información como variables locales de funciones, parámetros formales y relaciones de llamadas entre funciones.
2.4. Espacio de Métodos (Método Área)
Almacena las instrucciones de programas Java (código compilado por javac), incluyendo atributos y métodos de clases.
También guarda información relacionada con clases y atributos estáticos.
2.5. Stack Nativo
Servicios para métodos nativos utilizados por el JVM.
2.6. Notas Adicionales
En un proceso Java, solo hay una instancia de espacio de métodos y heap, pero puede haber múltiples contadores de programa y stacks (uno por cada hillo).
Cada hilo necesita su propio contador de programa y stack para mantener su flujo de ejecución.
3. Carga de Clases
3.1. Pasos Detallados de la Carga de Clases
Un programa Java corresponde a un archivo .java.
Después de compilar con javac, se genera un archivo .class.
Este archivo se lee desde el disco durante la ejecución y se carga en memoria por el JVM.
3.1.1. Carga
Se localiza el archivo .class mediante el nombre completo de la clase y se crea un objeto de clase.
3.1.2. Verificación
Comprueba si los datos del archivo .class son correctos y legales.
3.1.3. Preparación
Asigna memoria para variables de clase estáticas y establece valores iniciales (0 o null).
3.1.4. Resolución
Procesa constantes de cadenas en la clase, reemplazando referencias simbólicas con referencias directas.
Por ejemplo:
class Ejemplo {
private String texto = "hola";
}
El archivo .class contiene un área de pool constante para almacenar "hola".
3.1.5. Inicialización
Ejecuta bloques estáticos y asigna valores a variables estáticas.
3.2. Mecanismo de Carga - Modelo de Delegación de Padres
Los cargadores de clases delegan primero a sus padres antes de intentar cargar una clase ellos mismos.
JVM tiene tres cargadores de clases predeterminados:
- BootstrapClassLoader: Carga clases estándar.
- ExtensionClassLoader: Carga clases de extensión.
- ApplicationClassLoader: Carga clases de aplicaciones y bibliotecas de terceros.
4. Recolección de Basura (GC)
El «mecanismo de recolección de basura» permite a los programadores crear objetos sin preocuparse por liberar memoria manualmente.
4.1. Identificación de Objetos No Utilizados
4.1.1. Conteo de Referencias
Si un objeto no tiene referencias, se considera basura.
Ejemplo:
Ejemplo a = new Ejemplo();
Esto crea un objeto Ejemplo en memoria con una referencia inicializada en a.
4.1.2. Análisis de Alcanzabilidad
Determina si un objeto es accesible desde cualquier GC root. Los objetos inalcanzables se consideran basura.
4.2. Reciclaje Generacional
Divide objetos en jóvenes (nuevos) y viejos (antiguos), utilizando diferentes algoritmos de recolección.
4.2.1. Algoritmo de Copia
Usa dos mitades de memoria; copia objetos vivos a una mitad mientras libera la otra.
4.2.2. Algoritmo de Marca-Compactación
Reorganiza objetos vivos para compactarlos, permitiendo la liberación efiicente de memoria.
4.3. Reglas de Asignación de Objetos
- Nuevos objetos se colocan en la zona Eden.
- Grandes objetos van directamente al old generation.
- Objetos persistentes pasan al old generation después de varias copias.