El compilador JIT

El compilador Just-In-Time (JIT) es un componente del entorno de ejecución que mejora el rendimiento de las aplicaciones Java™ compilando códigos de bytes en código de máquina nativo en tiempo de ejecución.

Los programas Java están formados por clases, que contienen códigos de bytes de plataforma neutral que pueden ser interpretados por una JVM en muchas arquitecturas de sistemas diferentes. En tiempo de ejecución, la máquina virtual Java (JVM) carga los archivos de clases, determina la semántica de cada código de bytes individual y realiza el cálculo oportuno. El uso adicional de procesador y memoria durante la interpretación significa que una aplicación Java se ejecuta más lentamente que una aplicación nativa. El compilador JIT ayuda a mejorar el rendimiento de los programas Java compilando códigos de bytes en código de máquina nativo en tiempo de ejecución.

El compilador JIT está habilitado de forma predeterminada. Cuando se ha compilado un método, la JVM llama directamente al código compilado de dicho método en vez de interpretarlo. Teóricamente, si la compilación no requería tiempo de procesador y uso de memoria, compilar cada método podría permitir que la velocidad del programa Java coincidiera con la de una aplicación nativa.

La compilación JIT si que requiere uso de memoria y tiempo de procesador. Cuando la máquina virtual Java se inicia por primera vez, llama a miles de métodos. Compilar todos estos métodos puede tener un impacto considerable sobre el tiempo de inicio, aunque el programa consiga un rendimiento máximo muy bueno.

En la práctica, los métodos no se compilan la primera vez que se invocan. Para cada método, la JVM mantiene un recuento de invocación, que comienza en un valor de umbral de compilación predefinido y que disminuye cada vez que se llama al método. Cuando el recuento de invocación llega a cero, se desencadenará una compilación puntual para el método. Por lo tanto, los métodos utilizados con frecuencia se compilan en cuanto se ha iniciado la máquina virtual Java y los menos frecuentes se compilan mucho más tarde o bien no se compilan nunca. El umbral de compilación JIT permite que la máquina virtual Java se inicie rápidamente y siga teniendo un mayor rendimiento. El valor de umbral fue seleccionado para obtener un equilibrio óptimo entre los tiempos de inicio y el rendimiento a largo plazo.

El compilador JIT puede compilar un método en distintos niveles de optimización: cold, warm, hot, veryHoto scorching (consulte optlevel en -Xjit). Se espera que los niveles de optimización más altos proporcionen un mejor rendimiento, pero también tienen un coste de compilación superior en términos de CPU y de memoria. El nivel de optimización inicial o predeterminado para un método es warm, pero a veces la heurística JIT degrada el nivel de optimización a cold para mejorar el tiempo de arranque.

Se puede volver a compilar un método a un nivel de optimización más alto mediante distintos mecanismos. Uno de estos mecanismos es el muestreo: el compilador JIT mantiene una hebra de muestreo dedicada que se activa periódicamente y determina qué métodos Java aparecen más a menudo en la parte superior de la pila. Tales métodos se consideran más importantes para el rendimiento, y son candidatos para ser reoptimizados en los niveles superiores de hot, veryHot, o scorching.

Puede inhabilitar el compilador JIT, en cuyo caso se interpretará todo el programa Java. No se recomienda inhabilitar el compilador JIT, salvo para diagnosticar o buscar soluciones alternativas a los problemas de compilación de JIT.