Codemaker Computación por dentro

Computación por dentro Tema 4

Cómo se ejecuta un programa

La CPU no entiende Java. Solo entiende código máquina: instrucciones muy pequeñas escritas en binario. Entre lo que tú escribes y lo que la CPU ejecuta siempre hay una traducción.

Lo que hace la CPU: buscar, entender, ejecutar#

Una instrucción de código máquina hace muy poco: «suma estos dos números», «copia este valor a la memoria», «salta a la instrucción 20». La CPU repite siempre los mismos tres pasos:

La CPU repite tres pasos: busca la siguiente instrucción, la entiende y la ejecuta. El contador de programa marca por dónde va

  1. Buscar: trae de la RAM la siguiente instrucción.
  2. Entender: mira qué tiene que hacer.
  3. Ejecutar: lo hace.

Para saber por dónde va, la CPU tiene el contador de programa: la dirección de la siguiente instrucción. Normalmente avanza de una en una; un if o un bucle lo que hacen es saltar a otra instrucción.

Una sola línea de Java puede convertirse en varias instrucciones. Lo que hace rápido al ordenador no es que cada instrucción sea lista, sino que hace miles de millones por segundo.

Compilar o interpretar#

Hay dos formas de traducir un programa al idioma de la CPU:

Un lenguaje compilado se traduce entero a código máquina una vez; uno interpretado se traduce línea a línea cada vez que se ejecuta

Cómo esComo si…
Compilado (C, C++, Rust)Un compilador traduce todo el programa una vez y crea un ejecutable, como un .exeTraducir un libro entero y luego leer la traducción
Interpretado (Python, JavaScript)Un intérprete traduce y ejecuta cada línea en el momento, cada vez que se usaUn intérprete que va traduciendo mientras alguien habla

Lo compilado suele ser más rápido. Lo interpretado, más cómodo: no hay que compilar nada antes de probar. Pero el ejecutable compilado solo sirve para un tipo de ordenador: el de Windows no funciona en un Mac.

Java: un poco de los dos#

Java hace las dos cosas, y así consigue que el mismo programa funcione en cualquier ordenador:

javac convierte Hola.java en Hola.class, el bytecode. La JVM de Windows, de macOS o de Linux lo ejecuta en cada procesador

  1. javac compila tu .java, pero no a código máquina: a bytecode, un código máquina inventado para un ordenador que no existe. El resultado es el .class.
  2. La máquina virtual de Java (JVM) lee ese bytecode y lo traduce al procesador de verdad mientras se ejecuta. Hay una JVM para Windows, otra para macOS, otra para Linux… y las tres entienden el mismo .class.

Por eso decimos que Java se escribe una vez y funciona en todas partes. Y para que no sea lento, la JVM se fija en qué trozos se repiten mucho y los compila a código máquina sobre la marcha.

Ver el bytecode#

El bytecode se puede ver con javap -c, que viene con Java. Con este programa:

Java
public class Suma {
    public static void main(String[] args) {
        int a = 2;
        int b = 3;
        int c = a + b;
        System.out.println(c);
    }
}
Terminal
javac Suma.java
javap -c Suma

Esta es la parte del main (sin los comentarios que javap añade a la derecha):

Salida
       0: iconst_2
       1: istore_1
       2: iconst_3
       3: istore_2
       4: iload_1
       5: iload_2
       6: iadd
       7: istore_3
       8: getstatic     #7
      11: iload_3
      12: invokevirtual #13
      15: return

No hace falta entenderlo entero. Fíjate en que int c = a + b; se ha convertido en cuatro instrucciones: carga a (iload_1), carga b (iload_2), súmalos (iadd) y guarda el resultado en c (istore_3). Los números de la izquierda son las posiciones por las que va avanzando el contador de programa.

Nota

Abre cualquier .class con un editor hexadecimal y verás que todos empiezan por los mismos cuatro bytes: CA FE BA BE. Es la marca que pusieron los creadores de Java para reconocer sus ficheros.

Errores frecuentes#

Lo que pasaPor quéSolución
javac no se reconoce como comandoEl JDK no está instalado, o la terminal no lo encuentraMira Preparar el ordenador en los apuntes de Java
UnsupportedClassVersionErrorEl .class se compiló con un Java más nuevo que el que lo ejecutaEjecuta con la misma versión de Java con la que compilaste, o una más nueva
Cambio el código y se sigue ejecutando lo de antesSe está ejecutando el .class viejo: no has vuelto a compilarCompila otra vez con javac antes de ejecutar (VS Code lo hace solo al darle a Run)
Could not find or load main classEjecutas java en una carpeta donde no está el .class, o con el nombre malEjecuta en la carpeta del .class y escribe el nombre de la clase sin .class: java Suma