En el universo Java, que una aplicación inicie en pocos milisegundos con un consumo mínimo de memoria ha dejado de ser ciencia ficción. Gracias a GraalVM, Mandrel y sus tecnologías asociadas, hoy es posible hacerlo realidad.
En este artículo las desarmaremos para entender sus tecnologías, componentes, y cómo Quarkus puede empaquetar tu aplicación como un archivo ejecutable que corre sin una JVM instalada.
Resumen de componentes
Antes de empezar, aquí tienes una lista de los componentes principales:
| Componente | ¿Qué es? | Rol |
|---|---|---|
| GraalVM | Plataforma de ejecución de Oracle Labs | Proporciona la JVM y herramientas de compilación nativa |
| Mandrel | Distribución de GraalVM por Red Hat | Versión optimizada para Quarkus, 100% open source |
| native-image | Herramienta de compilación | Transforma tu app Java en un ejecutable nativo |
| SubstrateVM | Runtime ligero | Se embebe directamente en el ejecutable para proporcionar funcionalidades esenciales sin JVM externa |
¿Qué es GraalVM?
GraalVM es una plataforma de ejecución de alto rendimiento desarrollada por Oracle Labs. Aunque fue diseñada para soportar múltiples lenguajes, en el contexto de Java moderno destaca por algo revolucionario: la posibilidad de compilar aplicaciones Java como ejecutables nativos.
Puedes generar un único archivo ejecutable destinado a una arquitectura de hardware y sistema operativo específicos.
Una aplicación Java tradicional necesita:
- El archivo
.jarcon tu código - Una JVM instalada en el entorno de ejecución
Con GraalVM, puedes obtener:
- Un único archivo ejecutable para una arquitectura y sistema operativo específicos.
El ejecutable resultante no requiere una JVM instalada en el entorno de ejecución.
Esto es ideal para:
- Entornos cloud-native (aplicaciones diseñadas para la nube)
- Funciones serverless (que se ejecutan bajo demanda)
- Contenedores donde cada megabyte cuenta
Esta capacidad de transformar cualquier aplicación Java en un ejecutable autocontenido y compacto se logra con un componente fundamental: native-image.
El papel de native-image
native-image es la herramienta que permite transformar tu aplicación Java y sus dependencias en un ejecutable completamente nativo.
Lo logra mediante un exhaustivo análisis estático del código durante la compilación:
- Examina tu aplicación a fondo
- Identifica las clases, métodos y recursos estrictamente necesarios
- Descarta cualquier elemento que no se use
- Genera un ejecutable optimizado
Los resultados:
| Logro | Beneficio |
|---|---|
| Arranques ultrarrápidos | Milisegundos en lugar de segundos |
| Consumo mínimo de memoria | Ideal para contenedores |
| Comportamiento predecible | Sin sorpresas del JIT en runtime |
| Compatibilidad nativa | Ejecutable directo en el SO objetivo |
Pero native-image no está solo. Dentro de cada ejecutable nativo agrega un componente clave: SubstrateVM.
SubstrateVM: el runtime invisible
SubstrateVM es una máquina virtual nativa que forma parte de GraalVM, diseñada específicamente para ejecutar aplicaciones Java compiladas con native-image.
Piensa en SubstrateVM como un ‘motor de ejecución’ que se integra dentro del ejecutable nativo, permitiendo que la aplicación funcione sin una JVM instalada en el entorno de ejecución.
Su implementación está escrita mayormente en Java y se compila junto con tu aplicación durante el proceso de native-image. El resultado es un runtime nativo embebido en el ejecutable, que incluye solo los componentes realmente necesarios para interactuar con el sistema operativo.
A continuación se muestran algunas capacidades principales del runtime SubstrateVM que pueden quedar embebidas dentro del ejecutable, según lo que la aplicación requiera y lo que native-image determine como alcanzable durante el proceso de compilación.
| Capacidad del runtime SubstrateVM | Descripción |
|---|---|
| Gestión de memoria | Manejo automático de memoria mediante un GC específico para imágenes nativas |
| Gestión de hilos | Soporte básico de concurrencia sin el modelo completo de la JVM |
| APIs del JDK disponibles | Inclusión selectiva de clases y paquetes del JDK que realmente se usan |
| Soporte de reflexión (opcional) | Disponible únicamente si fue declarado explícitamente durante el build |
| Código de arranque del runtime | Inicialización mínima del proceso y del entorno de ejecución |
Estos elementos no son módulos configurables ni APIs públicas de SubstrateVM. Son partes internas del runtime que se incluyen (o no) automáticamente según el análisis de reachability realizado por native-image.
⚠️ Limitaciones importantes
Esta ligereza tiene un costo y es consecuencia directa del modelo de compilación nativa.
native-imagetrabaja bajo el supuesto de closed world, donde todo lo que se va a usar debe conocerse en tiempo de compilación.
Por este motivo, algunas características dinámicas de Java requieren configuración explícita o no están disponibles:
- Reflexión dinámica: necesita registro explícito en build-time
- Carga de clases en runtime: no soportada
- Proxies dinámicos: requieren registro previo mediante anotaciones o archivos de configuración
SubstrateVM es, en definitiva, el motor silencioso que impulsa los ejecutables nativos.
¿Qué es Mandrel?
Mandrel es una distribución especializada y reducida de GraalVM, mantenida por Red Hat y centrada exclusivamente en la compilación nativa.
Diferencias con GraalVM
| Aspecto | GraalVM | Mandrel |
|---|---|---|
| Mantenedor | Oracle Labs | Red Hat |
| Lenguajes soportados | Java, JavaScript, Python, Ruby, R, etc. | Solo Java |
| Base | OpenJDK con mejoras de Oracle | OpenJDK estándar |
| Licencia | Community (open source) o Enterprise (componentes propietarios) | 100% open source |
| Enfoque | Uso general, políglota | Optimizado para Quarkus |
| Soporte | Oracle (versión Enterprise) | Red Hat (con RHBQ) |
¿Por qué elegir Mandrel?
Mandrel es la opción recomendada cuando:
- Trabajas con Red Hat Build of Quarkus (RHBQ)
- Despliegas en OpenShift o contenedores Linux
- Necesitas soporte de Red Hat
- Priorizas estabilidad y trazabilidad
- Requieres cumplimiento de normas corporativas
ℹ️ Mandrel también incluye SubstrateVM, pero con ajustes y configuraciones adaptadas específicamente a los requisitos de Quarkus.
¿Qué sucede al compilar en modo nativo con Quarkus?
La compilación de aplicaciones Java como ejecutables nativos no es portable de la misma forma que un JAR tradicional.
El binario generado queda ligado al sistema operativo y a la arquitectura donde se realiza la compilación, ya que el proceso produce código máquina específico.
Por ejemplo:
- Si compilas en macOS ARM, el ejecutable solo funcionará en macOS ARM
- Si el objetivo es ejecutar en Linux x86_64, la compilación debe realizarse en un entorno compatible con Linux x86_64.
Esta restricción no es una limitación de Quarkus, sino una consecuencia directa de la compilación Ahead-of-Time utilizada por native-image.
La solución de Quarkus
Quarkus aborda este problema desplazando la compilación fuera del entorno del desarrollador. En lugar de depender del sistema operativo local, realiza la compilación nativa dentro de un contenedor Linux que actúa como entorno de destino controlado.
De esta forma, es posible generar ejecutables Linux desde macOS o Windows de manera reproducible y consistente. El binario resultante seguirá siendo específico de Linux, pero el proceso queda desacoplado del sistema anfitrión y se integra fácilmente con pipelines de CI/CD o entornos de construcción estandarizados.
Comandos para compilar en nativo (Windows, Mac OS, Linux)
Con Maven:
./mvnw package -PnativeCon Quarkus CLI:
quarkus build --native⚠️ La compilación nativa puede consumir bastante memoria (recomendado ≥ 4–8 GB RAM libre y CPU multi-core). En máquinas con recursos limitados, considera usar un contenedor o compilar en CI/CD.
El proceso paso a paso
- Quarkus delega la tarea a
native-image - native-image analiza tu código y dependencias
- Realiza compilación AOT (Ahead-of-Time — antes de ejecutar)
- Integra SubstrateVM en el ejecutable
- Aplica configuraciones de reflexión y recursos
- Genera el binario listo para ejecutarse
ℹ️ Si usas Red Hat Build of Quarkus, el proceso automáticamente emplea Mandrel como motor de compilación nativa.
Compilación en contenedor (Linux)
Para generar un ejecutable Linux desde cualquier sistema operativo, ejecuta:
./mvnw package -Pnative -Dquarkus.native.container-build=trueEsto descarga una imagen con Mandrel y compila dentro del contenedor, garantizando compatibilidad con Linux. La compilación nativa en contenedor requiere un motor de contenedores corriendo, como Docker o Podman. Quarkus es agnóstico al runtime y utiliza el motor disponible para ejecutar la imagen de compilación nativa.
GraalVM vs Mandrel: tabla comparativa
Ambas distribuciones comparten la capacidad de generar ejecutables nativos con SubstrateVM, pero sus objetivos son distintos:
| Criterio | GraalVM Community | Mandrel |
|---|---|---|
| Caso de uso principal | Exploración, múltiples lenguajes | Quarkus en producción |
| Tamaño de descarga | Mayor (incluye más componentes) | Menor (solo lo esencial) |
| Soporte | Oracle (versión Enterprise) | Red Hat (con RHBQ) |
| Actualizaciones | Ciclo de Oracle | Alineado con RHBQ |
| Compatibilidad OpenShift | Funciona | Optimizado y certificado |
| Ideal para | Desarrollo, experimentación | Producción empresarial |
¿Cuál elegir?
| Escenario | Recomendación |
|---|---|
| Estoy aprendiendo Quarkus | Cualquiera de las dos |
| Proyecto personal o startup | GraalVM Community |
| Empresa con soporte Red Hat | Mandrel + RHBQ |
| Despliegue en OpenShift | Mandrel |
🚀 Una nave, múltiples motores
Una aplicación Quarkus puede parecer sencilla, pero cuando se transforma en ejecutable nativo, se convierte en una nave de alto rendimiento ensamblada con precisión.
Comprender esta arquitectura no solo es fascinante: también es clave para tomar decisiones acertadas sobre compilación, rendimiento y despliegue en producción.
Para conocer los casos de uso de los ejecutables nativos, te recomiendo leer el artículo Jar vs ejecutables nativos.

