JavaRush /Blog Java /Random-ES /Compilación y ejecución de aplicaciones Java bajo el capó...
Павел Голов
Nivel 34
Москва

Compilación y ejecución de aplicaciones Java bajo el capó

Publicado en el grupo Random-ES

Contenido:

  1. Introducción
  2. Compilando en código de bytes
  3. Ejemplo de compilación y ejecución de programa.
  4. Ejecutar un programa en una máquina virtual
  5. Compilación justo a tiempo (JIT)
  6. Conclusión
Compilación y ejecución de aplicaciones Java bajo el capó - 1

1. Introducción

¡Hola a todos! Hoy me gustaría compartir conocimientos sobre lo que sucede bajo el capó de la JVM (máquina virtual Java) después de ejecutar una aplicación escrita en Java. Hoy en día, existen entornos de desarrollo de moda que le ayudan a evitar pensar en los aspectos internos de la JVM, compilar y ejecutar código Java, lo que puede hacer que los nuevos desarrolladores pasen por alto estos aspectos importantes. Al mismo tiempo, durante las entrevistas a menudo se hacen preguntas sobre este tema, por lo que decidí escribir un artículo.

2. Compilación en código de bytes

Compilación y ejecución de aplicaciones Java bajo el capó - 2
Empecemos con la teoría. Cuando escribimos cualquier aplicación, creamos un archivo con una extensión .javay colocamos código en el lenguaje de programación Java. Un archivo de este tipo que contiene código legible por humanos se denomina archivo de código fuente . Una vez que el archivo de código fuente esté listo, ¡debe ejecutarlo! Pero en el escenario contiene información comprensible sólo para los humanos. Java es un lenguaje de programación multiplataforma. Esto significa que los programas escritos en Java se pueden ejecutar en cualquier plataforma que tenga instalado un sistema de ejecución Java dedicado. Este sistema se llama Máquina Virtual Java (JVM). Para traducir un programa del código fuente a un código que la JVM pueda entender, es necesario compilarlo. El código entendido por la JVM se llama bytecode y contiene un conjunto de instrucciones que la máquina virtual ejecutará posteriormente. Para compilar el código fuente en código de bytes, hay un compilador javacincluido en el JDK (Java Development Kit). Como entrada, el compilador acepta un archivo con la extensión .java, que contiene el código fuente del programa, y ​​como salida, produce un archivo con la extensión .class, que contiene el código de bytes necesario para que la máquina virtual ejecute el programa. Una vez que un programa se ha compilado en código de bytes, se puede ejecutar utilizando una máquina virtual.

3. Ejemplo de compilación y ejecución de programas.

Supongamos que tenemos un programa simple, contenido en un archivo Calculator.java, que toma 2 argumentos de línea de comando numéricos e imprime el resultado de su suma:
class Calculator {
    public static void main(String[] args){
        int a = Integer.valueOf(args[0]);
        int b = Integer.valueOf(args[1]);

        System.out.println(a + b);
    }
}
Para compilar este programa en código de bytes, usaremos el compilador javacen la línea de comando:
javac Calculator.java
Después de la compilación, recibimos como salida un archivo con código de bytes Calculator.class, que podemos ejecutar usando la máquina java instalada en nuestra computadora usando el comando java en la línea de comando:
java Calculator 1 2
Tenga en cuenta que después del nombre del archivo, se especificaron 2 argumentos de la línea de comando: números 1 y 2. Después de ejecutar el programa, se mostrará en la línea de comando el número 3. En el ejemplo anterior, teníamos una clase simple que vive por sí sola . ¿Pero qué pasa si la clase está en algún paquete? Simulemos la siguiente situación: creemos directorios src/ru/javarushy coloquemos nuestra clase allí. Ahora se ve así (agregamos el nombre del paquete al principio del archivo):
package ru.javarush;

class Calculator {
    public static void main(String[] args){
        int a = Integer.valueOf(args[0]);
        int b = Integer.valueOf(args[1]);

        System.out.println(a + b);
    }
}
Compilemos dicha clase con el siguiente comando:
javac -d bin src/ru/javarush/Calculator.java
En este ejemplo, utilizamos una opción de compilación adicional -d binque coloca los archivos compilados en un directorio bincon una estructura similar al directorio src, pero el directorio bindebe crearse con anticipación. Esta técnica se utiliza para evitar confundir archivos de código fuente con archivos de código de bytes. Antes de ejecutar el programa compilado, conviene explicar el concepto classpath. Classpathes la ruta relativa a la cual la máquina virtual buscará paquetes y clases compiladas. Es decir, de esta forma le decimos a la máquina virtual qué directorios del sistema de archivos son la raíz de la jerarquía de paquetes Java. ClasspathSe puede especificar al iniciar el programa usando la bandera -classpath. Lanzamos el programa usando el comando:
java -classpath ./bin ru.javarush.Calculator 1 2
En este ejemplo, requerimos el nombre completo de la clase, incluido el nombre del paquete en el que reside. El árbol de archivos final se ve así:
├── src
│     └── ru
│          └── javarush
│                  └── Calculator.java
└── bin
      └── ru
           └── javarush
                   └── Calculator.class

4. Ejecución del programa mediante una máquina virtual.

Entonces lanzamos el programa escrito. Pero, ¿qué sucede cuando una máquina virtual inicia un programa compilado? Primero, averigüemos qué significan los conceptos de compilación e interpretación de código. La compilación es la traducción de un programa escrito en un lenguaje fuente de alto nivel a un programa equivalente en un lenguaje de bajo nivel similar al código de máquina. La interpretación es un análisis, procesamiento y ejecución inmediata operador por declaración (comando por línea, línea por línea) del programa fuente o solicitud (a diferencia de la compilación, en la que el programa se traduce sin ejecutarlo). El lenguaje Java tiene un compilador ( javac) y un intérprete, que es una máquina virtual que convierte el código de bytes en código de máquina línea por línea y lo ejecuta inmediatamente. Así, cuando ejecutamos un programa compilado, la máquina virtual comienza a interpretarlo, es decir, a convertir línea por línea el código de bytes en código de máquina, así como su ejecución. Desafortunadamente, la interpretación pura del código de bytes es un proceso bastante largo y hace que Java sea lento en comparación con sus competidores. Para evitar esto, se introdujo un mecanismo para acelerar la interpretación del código de bytes por parte de la máquina virtual. Este mecanismo se llama compilación justo a tiempo (JITC).

5. Compilación justo a tiempo (JIT)

En términos simples, el mecanismo de compilación Just-In-Time es el siguiente: si hay partes del código en el programa que se ejecutan muchas veces, entonces se pueden compilar una vez en código de máquina para acelerar su ejecución en el futuro. Después de compilar dicha parte del programa en código de máquina, con cada llamada posterior a esta parte del programa, la máquina virtual ejecutará inmediatamente el código de máquina compilado en lugar de interpretarlo, lo que naturalmente acelerará la ejecución del programa. La aceleración del programa se logra aumentando el consumo de memoria (¡necesitamos almacenar el código de máquina compilado en algún lugar!) y aumentando el tiempo dedicado a la compilación durante la ejecución del programa. La compilación JIT es un mecanismo bastante complejo, así que repasemos el principio. Hay 4 niveles de compilación JIT de código de bytes en código de máquina. Cuanto mayor sea el nivel de compilación, más compleja será, pero al mismo tiempo la ejecución de dicha sección será más rápida que una sección con un nivel más bajo. JIT: el compilador decide qué nivel de compilación establecer para cada fragmento de programa en función de la frecuencia con la que se ejecuta ese fragmento. Debajo del capó, la JVM utiliza 2 compiladores JIT: C1 y C2. El compilador C1 también se denomina compilador cliente y es capaz de compilar código sólo hasta el tercer nivel. El compilador C2 es responsable del cuarto nivel de compilación, el más complejo y rápido.
Compilación y ejecución de aplicaciones Java bajo el capó - 3
De lo anterior, podemos concluir que para aplicaciones cliente simples, es más rentable utilizar el compilador C1, ya que en este caso es importante para nosotros la rapidez con la que se inicia la aplicación. Las aplicaciones de larga duración del lado del servidor pueden tardar más en iniciarse, pero en el futuro deben funcionar y realizar su función rápidamente; aquí el compilador C2 es adecuado para nosotros. Al ejecutar un programa Java en la versión x32 de JVM, podemos especificar manualmente qué modo queremos usar usando las banderas -clienty -server. Cuando se especifica este indicador, -clientla JVM no realizará optimizaciones complejas del código de bytes, lo que acelerará el tiempo de inicio de la aplicación y reducirá la cantidad de memoria consumida. Al especificar la bandera, -serverla aplicación tardará más en iniciarse debido a optimizaciones complejas del código de bytes y utilizará más memoria para almacenar el código de máquina, pero el programa se ejecutará más rápido en el futuro. En la versión x64 de JVM, el indicador -clientse ignora y la configuración del servidor de aplicaciones se usa de forma predeterminada.

6. Conclusión

Con esto concluye mi breve descripción de cómo funciona la compilación y ejecución de una aplicación Java. Puntos principales:
  1. El compilador javac convierte el código fuente de un programa en código de bytes que se puede ejecutar en cualquier plataforma en la que esté instalada la máquina virtual Java;
  2. Después de la compilación, la JVM interpreta el código de bytes resultante;
  3. Para acelerar las aplicaciones Java, la JVM utiliza un mecanismo de compilación Just-In-Time que convierte las secciones de un programa ejecutadas con mayor frecuencia en código de máquina y las almacena en la memoria.
Espero que este artículo te haya ayudado a comprender mejor cómo funciona nuestro lenguaje de programación favorito. Gracias por leer, ¡las críticas son bienvenidas!
Comentarios
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION