Saltar a contenido

UD 1 - P14: Solución orientativa de código intermedio y JVM

Solución orientativa de la práctica P14

Estas respuestas sirven para contrastar el trabajo, no son una única redacción posible. Se aceptan explicaciones distintas si identifican correctamente los artefactos, las herramientas y los requisitos del entorno. La secuencia exacta de bytecode puede variar entre versiones del JDK.

Preparación y código fuente

Una solución posible para Suma.java es:

public class Suma {
    public static void main(String[] args) {
        int num1 = 5;
        int num2 = 7;
        int resultado = num1 + num2;
        System.out.println("El resultado es: " + resultado);
    }
}

Suma.java es el código fuente que se escribe y modifica. El nombre del archivo debe coincidir con el de la clase pública Suma.

Ejercicio 1: reconocer herramientas y artefactos

Pregunta 1.a: Completa una tabla con Suma.java, Suma.class, javac, java, javap y la JVM.

Subpregunta 1.a.1: ¿Qué representa o hace cada elemento?

Subpregunta 1.a.2: ¿En qué momento interviene cada elemento?

Subpregunta 1.a.3: ¿Cuál es código fuente, cuál es bytecode, cuáles son herramientas y cuál es el entorno de ejecución?

Respuesta orientativa: Una tabla posible es:

Elemento Tipo o función Momento en el que interviene
Suma.java Código fuente Java, legible y modificable. Se escribe y se actualiza antes de compilar.
javac Compilador de Java incluido en el JDK. Traduce el fuente a bytecode y genera Suma.class.
Suma.class Archivo de clase que contiene bytecode para la JVM. Se genera al compilar y la JVM lo carga al ejecutar el programa.
java Herramienta que inicia el entorno de ejecución Java. Busca y carga la clase solicitada y pone en marcha el método main.
JVM Entorno que verifica, interpreta y/o compila bytecode para ejecutarlo. Procesa la clase en el sistema donde se inicia el programa.
javap Herramienta de inspección de archivos de clase. Muestra información de la clase; con -c presenta instrucciones de bytecode.

El código fuente y el bytecode son representaciones distintas del mismo programa. La JVM no es un procesador físico ni una máquina virtual que necesariamente ejecute un sistema operativo completo; es un entorno de ejecución para bytecode Java.

Ejercicio 2: proceso de ejecución y portabilidad

Pregunta 2.a: ¿Qué diferencia hay entre el código fuente y el bytecode de Suma?

Respuesta orientativa: El código fuente está escrito en Java y lo mantiene el equipo de desarrollo. El bytecode es la representación que produce el compilador javac; se guarda en Suma.class y está diseñado para que lo procese una JVM, no para que una CPU concreta lo ejecute directamente.

Subpregunta 2.b: ¿Qué hace javac y qué hace la herramienta java?

Respuesta orientativa: javac Suma.java compila el fuente y, si no hay errores, genera el archivo de clase con bytecode. java Suma inicia el entorno de ejecución, carga y verifica la clase, resuelve los elementos que necesite y solicita ejecutar su método main. En esta práctica no se usa un comando de enlazado independiente como el de GCC; las tareas de carga y resolución de clases forman parte del entorno JVM.

Subpregunta 2.c: ¿Por qué no se ejecuta Suma.class directamente haciendo doble clic o escribiendo su nombre como si fuera un programa nativo?

Respuesta orientativa: El archivo .class contiene bytecode, no un ejecutable nativo con instrucciones y formato de carga para el sistema operativo y la CPU concretos. Se inicia mediante una JVM compatible, por ejemplo con java Suma.

Subpregunta 2.d: ¿Qué representa iadd en la salida de javap -c?

Respuesta orientativa: iadd es una instrucción de bytecode que suma valores enteros en la pila de operandos de la JVM.

Subpregunta 2.d.1: ¿Por qué esa salida no es código máquina de tu procesador?

Respuesta orientativa: La salida de javap -c representa instrucciones de la máquina virtual. No muestra las instrucciones nativas específicas de la CPU que podrían utilizarse durante la ejecución.

Subpregunta 2.e: ¿Qué aporta la JVM a la portabilidad?

Respuesta orientativa: La JVM proporciona un entorno común para cargar y ejecutar bytecode en plataformas distintas.

Subpregunta 2.e.1: ¿Qué debe seguir siendo compatible en el equipo de destino?

Respuesta orientativa: La portabilidad no elimina los requisitos: debe haber una implementación de JVM compatible con la versión del archivo .class, y deben estar disponibles las bibliotecas, dependencias y configuraciones requeridas. Algunas JVM interpretan bytecode y/o compilan partes a código nativo con JIT; la estrategia depende de la implementación.

Pregunta 2.f: Compara este proceso con la compilación nativa habitual de C o C++.

Subpregunta 2.f.1: ¿Qué artefacto se distribuye en cada caso?

Respuesta orientativa: En Java se distribuye normalmente el bytecode (por ejemplo, el archivo .class o un .jar) para que lo procese una JVM compatible. En una compilación nativa habitual de C o C++ se distribuye un ejecutable o paquete generado para un sistema y una arquitectura determinados.

Subpregunta 2.f.2: ¿Qué tendrías que comprobar para ejecutarlo en otro sistema?

Respuesta orientativa: En Java, javac genera bytecode que se distribuye para que lo ejecute una JVM compatible; el mismo archivo de clase puede reutilizarse en varias plataformas cuando se cumplen los requisitos del entorno. En una compilación nativa habitual de C o C++, el compilador y el enlazador generan un ejecutable para un sistema operativo y una arquitectura concretos. Para otro destino normalmente hay que preparar una compilación o un paquete compatible. La comparación describe flujos habituales y no significa que todos los lenguajes o herramientas tengan un único modo de ejecución.

Resultados iniciales de los pasos 4.3 y 4.4

Paso 4.3 — Enunciado: En la misma carpeta, ejecuta java Suma para iniciar el método main mediante la JVM y comprueba la salida.

Resultado orientativo: Después de javac Suma.java se espera encontrar Suma.class. Al ejecutar java Suma, la salida es:

El resultado es: 12

Paso 4.4 — Enunciado: Ejecuta javap -c Suma y localiza en main instrucciones relacionadas con los valores, la suma y la salida.

Resultado orientativo: Para inspeccionar el bytecode se ejecuta:

javap -c Suma

La salida contiene el método main e instrucciones asociadas a cargar los operandos, sumar y mostrar el resultado. En compilaciones comunes se observa una instrucción iadd para la suma de enteros. Los índices, las constantes y la forma de construir la cadena pueden cambiar; no se debe exigir que toda la salida coincida carácter por carácter con una captura de referencia.

Ejercicio 3: modificar los operandos y reconstruir

Pregunta 3.a: Cambia los operandos a 17 y 25.

Subpregunta 3.a.1: Antes de ejecutar, incluye tu predicción del resultado.

Respuesta orientativa: La suma esperada es 17 + 25 = 42.

Subpregunta 3.a.2: Explica qué ocurriría si editases Suma.java pero ejecutases el .class antiguo sin recompilar.

Respuesta orientativa: Se ejecutaría el bytecode generado antes del cambio y podría aparecer el resultado anterior, aunque el fuente muestre los valores nuevos.

Subpregunta 3.a.3: ¿Qué salida obtienes al ejecutar?

Respuesta orientativa: La salida debe ser:

El resultado es: 42

Subpregunta 3.b: Guarda el fuente, vuelve a compilarlo con javac y ejecuta la clase actualizada con java Suma. Registra las órdenes.

Respuesta orientativa: Vuelve a ejecutar:

javac Suma.java
java Suma

En Java no se ejecuta un paso de enlazado independiente como en la práctica de GCC. La JVM carga, verifica y resuelve las clases que necesita durante la ejecución. Recompilar genera el nuevo Suma.class; java Suma ejecuta esa versión actualizada.

Ejercicio 4: prácticas generales de trabajo

Pregunta 4.a: Enumera al menos cuatro prácticas generales de trabajo observadas en la actividad y explica cómo ayudan a evitar errores o a reproducir el proceso.

Respuesta orientativa: Son válidas, entre otras, estas respuestas:

  • Comprobar y registrar las herramientas y sus versiones: facilita explicar diferencias entre resultados y detectar si falta el JDK o si el entorno de destino es incompatible.
  • Separar el fuente de los artefactos generados: Suma.java se conserva como base editable y Suma.class se vuelve a generar; así se evita confundir el material de trabajo con una salida de compilación.
  • Anotar las órdenes y comprobar cada etapa: permite repetir el proceso y localizar si el fallo se produce al compilar, ejecutar o inspeccionar.
  • Leer los diagnósticos completos: ayuda a identificar el archivo, la línea o la incompatibilidad que origina el problema antes de modificar el programa a ciegas.
  • Volver a construir tras cambiar el fuente: evita ejecutar bytecode desactualizado y atribuir su resultado al código recién editado.
  • Comprobar los requisitos del sistema de destino: recuerda que un artefacto portable todavía puede depender de una versión del entorno de ejecución, bibliotecas y configuración.
  • Verificar la salida y el artefacto: comparar 12 y después 42, junto con la existencia de Suma.class, aporta evidencia de que se ha seguido el ciclo correctamente.

Estas prácticas son transferibles a otras cadenas de compilación, aunque sus comandos y formatos de archivo cambien. Se relacionan con la teoría al distinguir fases y artefactos, comprobar las herramientas y no confundir portabilidad con ausencia de requisitos.

Entregable

Pregunta 5.a: Entrega Suma.java y un README.md identificado con tu nombre, módulo, unidad y práctica. Incluye las versiones del entorno, las órdenes utilizadas, la tabla, las respuestas, una captura o transcripción de las dos ejecuciones, un fragmento de javap -c y la reflexión sobre las prácticas generales. Adjunta también Suma.class o, si el aula no admite archivos binarios, una evidencia verificable de su generación.

Comprobación del entregable: El README.md identifica a quien lo entrega y documenta el entorno, los comandos, los resultados y las reflexiones solicitadas. Se adjuntan Suma.java y Suma.class cuando el aula admite binarios; si no, se aporta evidencia verificable de la generación de la clase.

Ejercicio 6: ampliación opcional de portabilidad

Enunciado 6.a: Intenta ejecutar el mismo Suma.class en otro sistema operativo o equipo. Indica qué archivos copiaste, la versión de JVM disponible y si hubo algún requisito de versión o dependencia que afectase al resultado. La prueba en otro sistema es opcional.

Respuesta orientativa: Si se copia solo Suma.class a otro equipo, puede ejecutarse con java Suma cuando haya una JVM compatible con la versión del bytecode y estén disponibles las dependencias. Si el destino usa una JVM demasiado antigua, puede producirse un error de versión de clase no compatible. La prueba no demuestra independencia total de plataforma: evidencia que el mismo artefacto puede funcionar en entornos compatibles.

Fuentes y referencias