Todos los programas tienen un entorno de tiempo de ejecución. Tendemos a olvidar esto, pero está ahí. Lib estándar para C que envuelve las llamadas del sistema al sistema operativo. Objective-C tiene su tiempo de ejecución que envuelve todo el paso de mensajes.
Con Java, el tiempo de ejecución es la JVM. La mayoría de las implementaciones de Java con las que la gente está familiarizada son similares al HotSpot JVM, que es un intérprete de código de bytes y un compilador JIT.
Esta no tiene que ser la única implementación. No hay absolutamente nada que diga que no puede construir un tiempo de ejecución lib-esque estándar para Java y compilar el código en código máquina nativa y ejecutarlo dentro del tiempo de ejecución que maneja las llamadas de nuevos objetos en mallocs y el acceso a archivos en llamadas del sistema en la máquina. Y eso es lo que hace el compilador Ahead Of Time (AOT en lugar de JIT). Llama a ese tiempo de ejecución lo que va ... que se podría llamar una implementación JVM (y que no sigue la especificación JVM) o un entorno de tiempo de ejecución o lib estándar de Java. Está allí y hace esencialmente lo mismo.
Se podría hacer reimplementando javac
para apuntar a la máquina nativa (eso es lo que hizo GCJ ). O podría hacerse traduciendo el código de byte generado por el código de javac
máquina (o byte) para otra máquina, eso es lo que hace Android. Según Wikipedia, eso es lo que también hace Excelsior JET ("El compilador transforma el código de bytes de Java portátil en ejecutables optimizados para el hardware y sistema operativo (SO) deseado"), y lo mismo es cierto para RoboVM .
Hay complicaciones adicionales con Java que significa que esto es muy difícil de hacer como un enfoque exclusivo. La carga dinámica de clases ( class.forName()
) u objetos proxy requiere una dinámica que los compiladores de AOT no proporcionan fácilmente y, por lo tanto, sus respectivas JVM también deben incluir un compilador JIT (Excelsior JET) o un intérprete (GCJ) para manejar clases que no se pueden precompilar nativo.
Recuerde, la JVM es una especificación , con muchas implementaciones . La biblioteca estándar C también es una especificación con muchas implementaciones diferentes.
Con Java8, se ha trabajado bastante en la compilación AOT. En el mejor de los casos, uno solo puede resumir AOT en general dentro de los límites del cuadro de texto. Sin embargo, en la JVM Language Summit para 2015 (agosto de 2015), hubo una presentación: Java Goes AOT (video de youtube). Este video dura 40 minutos y abarca muchos de los aspectos técnicos más profundos y puntos de referencia de rendimiento.
gcj
ejemplo ejecutable mínimoTambién puede observar una implementación de código abierto como
gcj
(ahora obsoleta). Por ejemplo, archivo Java:Luego compila y ejecuta con:
Ahora eres libre de descompilarlo y ver cómo funciona.
file Main.o
dice que es un archivo elfo.readelf -d Main | grep NEEDED
dice que depende de las bibliotecas dinámicas:Entonces libgcj.so debe ser donde se implementa la funcionalidad Java.
Luego puede descompilarlo con:
y ver exactamente cómo se implementa.
Se parece mucho a C ++, muchas alteraciones de nombres y llamadas indirectas a funciones polimórficas.
Me pregunto cómo se iniciará la recolección de basura. Merecería la pena examinarlo: /programming/7100776/garbage-collection-implementation-in-compiled-languages y otros lenguajes compilados con GC como Go.
Probado en Ubuntu 14.04, GCC 4.8.4.
También eche un vistazo a https://en.wikipedia.org/wiki/Android_Runtime , la columna vertebral de Android 5 en adelante, que hace todo lo posible para optimizar las aplicaciones de Android.
fuente