Saltar al contenido principal

Compilación y Builds de la JVM

Si vas a construir algo serio en el ecosistema Java, ayuda entender qué pasa realmente con tu código después de que guardás. Conocés los lenguajes (Java, Kotlin, Groovy) y sabés que todos compilan a bytecode que corre en la JVM. ¿Pero qué pasa en el medio? Ahí es donde entran las herramientas de build y el proceso de compilación.

Herramientas de Build

Las herramientas de build son gestores de proyecto. Se encargan del trabajo pesado:

  • Descargar bibliotecas/dependencias
  • Definir pasos (compilar código, correr tests, construir archivos JAR)
  • Mantener la estructura del proyecto estándar y organizada

Típicamente vas a encontrarte con Maven o Gradle. Para la mayoría de los proyectos Spring Boot, no importa cuál elijas. Ambos te llevan exactamente al mismo destino.

AspectoMavenGradle
ConfiguraciónUsa XML (estructurado con <tags>)Usa Kotlin/Groovy (sintaxis tipo código)
FlexibilidadConvenciones estrictas y estandarizadasAltamente customizable (soporta lógica como if-else)
Casos de UsoProyectos Java legacy o empresarialesApps Android, proyectos modernos Java/Kotlin

Ambos descargan de Maven Central, ambos compilan de la misma manera, ambos producen los mismos JARs.

El Directorio de Build

Maven lo llama target/, Gradle lo llama build/. No importa. Es tu directorio de salida del build, y contiene:

DirectorioPropósito
classes/java/main/Clases de producción compiladas
classes/resources/Recursos empaquetados con el JAR
test-results/Resultados de ejecución de tests
generated-sources/Código generado por procesadores de anotaciones (Lombok, MapStruct, etc.)
my-app.jarTu artefacto de producción

El directorio de build existe, pero para el desarrollo cotidiano, raramente necesitás ir ahí. Hay momentos raros en los que vas a querer explorar el directorio de build:

  1. Debuggeando fallos de tests: Abrí test-results/ para ver reportes XML y entender qué salió mal
  2. Entendiendo código generado: Revisá generated-sources/ cuando procesadores de anotaciones como Lombok están creando código que no entendés
  3. Investigando fallos misteriosos de CI: Verificá que el directorio de build contenga exactamente lo que esperás
  4. Corriendo tests manuales: Podés correr directamente java -jar build/my-app.jar sin herramientas de build

JAR

Tu JAR de producción no tiene huellas digitales de Maven o Gradle. Son idénticos desde la perspectiva de la JVM.

  1. El manejo de dependencias es idéntico: La diferencia es la sintaxis (pom.xml vs build.gradle), no el comportamiento.
  2. Los JARs生成ados son gemelos:
    • Misma disposición de clases
    • Archivo MANIFEST.MF idéntico
    • Mismos archivos de recursos
    • Mismos metadatos
  3. Los IDEs no les importa: IntelliJ IDEA auto-detecta ambos y muestra la barra de herramientas correspondiente de Maven o Gradle.

Bytecode

Aunque Java, Kotlin y Groovy todos compilan a bytecode de la JVM, la calidad y características de ese bytecode difieren significativamente.

Scroll to zoom • Drag corner to resize
AspectoJavaKotlinGroovy
CompilaciónDirecto a bytecodeDirecto a bytecode, luego optimizadoCompilación dinámica, genera bytecode verboso
OverheadNinguno (cuando compilado)Mínimo (sin overhead de runtime)Alto (características dinámicas agregan chequeos de runtime)
Transformaciones AST❌ Ninguna❌ Ninguna✅ Sí (vía @Canonical, @Builder, etc.)
Seguridad de TiposEn tiempo de compilaciónEn tiempo de compilación (con null-safety)En runtime (tipado dinámico)
Tamaño del BytecodeCompactoCompactoAbultado (frames extra, chequeos, proxies)
VisibilidadClaro en IDEClaro en IDEA menudo invisible (código generado)

¿Qué Son las Transformaciones AST?

Las transformaciones AST (Abstract Syntax Tree) son mecanismos de generación de código en tiempo de compilación que modifican tu código fuente antes de que se convierta en bytecode. Son características poderosas que generan código boilerplate para vos.

Ejemplos comunes en Groovy:

  • @Canonical → genera automáticamente métodos equals, hashCode, toString
  • @Builder → genera un patrón Builder completo con todos los métodos necesarios
  • @Slf4j → genera una instancia de logger para logging

Estas transformaciones generan código Java real que se compila junto con tus archivos fuente. No podés verlo en tu editor, pero existe en el directorio de build.