Compilación y ejecución
El proceso completo
1. Escribir código (.java) ↓2. Compilar (javac) ↓3. Bytecode (.class) ↓4. Ejecutar (java) ↓5. JVM carga y ejecutaCompilación
Compilar un archivo
javac HolaMundo.javaGenera HolaMundo.class (bytecode).
Compilar múltiples archivos
javac Archivo1.java Archivo2.java Archivo3.javaO con wildcard:
javac *.javaEspecificar directorio de salida
javac -d bin src/HolaMundo.javaGenera los .class en el directorio bin/.
Especificar classpath
Para incluir dependencias:
javac -cp libs/biblioteca.jar src/Main.javaEjecución
Ejecutar una clase
java HolaMundoNota: Sin extensión .class.
Especificar classpath
java -cp bin:libs/biblioteca.jar HolaMundoEn Windows usa ; en lugar de ::
java -cp bin;libs\biblioteca.jar HolaMundoCon archivos JAR
java -jar miapp.jarBytecode
Ver bytecode
javap -c HolaMundo.classEjemplo:
public class HolaMundo { public static void main(String[] args) { System.out.println("Hola"); }}Bytecode:
public static void main(java.lang.String[]); Code: 0: getstatic #7 // Field java/lang/System.out 3: ldc #13 // String Hola 5: invokevirtual #15 // Method println 8: returnInstrucciones:
getstatic: Obtiene campo estático (System.out)ldc: Carga constante ("Hola")invokevirtual: Llama método (println)return: Retorna
JIT Compiler
Interpretación vs Compilación
Interpreter: Ejecuta bytecode línea por línea (lento, pero inicia rápido).
JIT Compiler: Compila bytecode a código nativo en tiempo de ejecución (rápido).
La JVM empieza con el interpreter y detecta "hot spots" (código que se ejecuta frecuentemente) para compilarlos con JIT.
Niveles de compilación
C1 (Client Compiler): Compilación rápida, optimización básica.
C2 (Server Compiler): Compilación lenta, optimización agresiva.
Tiered Compilation (por defecto): Combina C1 y C2.
Inicio → Interpreter → C1 → C2 (rápido) (medio) (optimizado)Optimizaciones de la JVM
Inlining
Reemplaza llamadas a métodos por el código del método:
// Código originalpublic int sumar(int a, int b) { return a + b;}
public void calcular() { int resultado = sumar(3, 5);}
// Optimizado (inlining)public void calcular() { int resultado = 3 + 5;}Dead Code Elimination
Elimina código que nunca se ejecuta:
public void metodo() { if (false) { // Este código se elimina }}Loop Unrolling
Desenrolla bucles para reducir overhead:
// Código originalfor (int i = 0; i < 4; i++) { System.out.println(i);}
// OptimizadoSystem.out.println(0);System.out.println(1);System.out.println(2);System.out.println(3);Escape Analysis
Determina si un objeto escapa del ámbito de un método. Si no escapa, puede allocarlo en el stack en lugar del heap (más rápido).
Opciones de JVM
Ajustar memoria
java -Xmx2g -Xms512m Main-Xmx2g: Máximo 2GB de heap-Xms512m: Inicial 512MB de heap
Configurar GC
java -XX:+UseG1GC MainUseG1GC: Usa G1 Garbage CollectorUseZGC: Usa ZGC (baja latencia)
Imprimir información de JIT
java -XX:+PrintCompilation MainMuestra qué métodos se compilan con JIT.
Crear un JAR
JAR ejecutable
Crear:
jar cfe miapp.jar Main Main.class Utilidades.classc: Crearf: Especificar archivoe: Punto de entrada (clase Main)
Ejecutar:
java -jar miapp.jarManifest
MANIFEST.MF:
Manifest-Version: 1.0Main-Class: MainHerramientas
javac
Compilador de Java.
java
Lanza la JVM para ejecutar programas.
javap
Desensambla bytecode.
jar
Crea y manipula archivos JAR.
jshell (Java 9+)
REPL para experimentar:
jshell| Welcome to JShelljshell> int x = 5;x ==> 5jshell> x * 2$2 ==> 10Próximo paso
Aprende sobre el Garbage Collector: Garbage Collection →