💥💻Comenzando con Java: Presentación, orígenes e historia del lenguaje de programación, Hola Mundo…

[English Version]

David Bernal González
59 min readAug 16, 2021

En este mega post, vamos a hacer un especie de viaje en el tiempo que nos va a permitir profundizar en aterrizar en la tecnología, entendiendo cuál es la filosofía que esconder este el lenguaje antes de ponernos a picar código, haciendo una pequeña vista de pájaro, cogiendo un poco de “culturilla” sobre varios aspectos, hablando sobre algunas anécdotas de este lenguaje, conocido su historia, etc.

La finalidad de todo esto, será la de obtener un gran conocimiento, una gran visión de cómo funciona internamente Java y entender el porqué realizamos según que determinados procedimientos.

📖 Tabla de contenido 📖

1. Presentación de Java

2. Historia de SUN Microsystems

3. ¿Por qué nace Java?

4. SUN arranca el proyecto de creación de un nuevo lenguaje

5. Más historia/culturilla sobre Java

6. Ediciones o Tipos de Java: ME, SE, EE y FX

7. SUN es absorbida (comprada) por Oracle

8. Entornos de ejecución de Java: JRE vs JDK

9. La disputa de la década, el juicio que enfrenta a Oracle VS Google

10. Entendiendo los sistemas de numeración

11. Configurando e instalado el Kit de Desarrollo (JDK) para poder desarrollar con Java

12. Compilación manual de un programa en Java y funcionamiento de la JVM

13. Compilación y descompilación manual en Java (sin IDE)

14. Descompilación manual/automática de un archivo en bytecode, transformación de bytecode a hexadecimal e historia de CAFEBABE

15. Trabajando con un IDE

16. Cierre del articulo

16.1 → Conclusión final

1. Presentación de Java

1.1) ¿Qué es Java?

  • Lenguaje de programación de propósito general (diseñados para resolver todo tipo de problemas).
  • Catalogado como un lenguaje de alto nivel.

1.2) Tipos de lenguajes de programación

Clasificación en función de la distancia con la que interactúe dicho lenguaje de programación sobre el hardware del dispositivo:

  • Lenguajes de bajo nivel: utilizan términos muy cercanos a la máquina (recordad que la máquina sólo entiende el lenguaje binario, es decir, 0 y 1).
  • Lenguajes de alto nivel: utilizan términos más cercanos a las personas, normalmente en inglés como son: IF (si), ELSE (sino), WHILE (mientras), etc.

1.3) ¿Por qué aprender Java?

Java destaca por ser uno de los lenguajes más usados y más populares del mundo.

Muestra de ello, es que si revisamos el siguiente gráfico sacado de TIOBE, podemos comprobar que Java junto a C y C++ ha dominado/reinado la programación comercial durante más de 20 años.

El que Java tenga tanta popularidad como lenguaje de programación nos asegura que muchos proyectos han sido desarrollados con dicha tecnología. Y por tanto, nos garantizará que habrá muchas ofertas en la que se busquen perfiles con Java (“Javeros”).

2. Historia de SUN Microsystems

2.1) Fundación de SUN

SUN Microsystems, fue fundada en 1982 en Santa Clara, California (EEUU).

La compañía estaba formada por 4 miembros: un alemán (Andreas Von Bechtolsheim) junto a 3 estadounidenses (Vinod Khosla, Scott McNealy y Bill Joy).

2.2) Significado de las siglas de SUN

Las siglas de SUN provienen de las iníciales del nombre del proyecto que se creó con el fin de conectar en red las bibliotecas de la Universidad de Stanford.

El logo oficial de SUN es el siguiente:

2.3) ¿A qué se dedica SUN?

SUN es una empresa que se dedicaba a la informática tanto a la creación y distribución de software (sistemas operativos u otro tipo de software) como a la de hardware (estaciones de trabajo, servidores, componentes informáticos, etc.) . Además de ofrecer servicios informáticos (consultoría).

SUN, trabajaba en muchos proyectos como por ejemplo:

  • «Not a pizza box» («No es una caja de pizza») estación de trabajo (workstation) creada por SUN en 1982. La cual presentaba una CPU Motorola 68000, 1 MB de memoria y una pantalla gráfica de un millón de píxeles.
  • SUN trabajó también en el desarrollo del protocolo TCP/IP (1984) para el que creó el lema de «The network is the computer» («La red es la computadora»).

Este lema fue creado por John Gage, un gran amigo de Bill Joy y el quinto empleado de SUN. Que ya adelantó en aquel entonces el gran futuro que tendría la computación en la nube con su famosa frase “The network is the computer”.

3. ¿Por qué nace Java?

3.1) Analizando las necesidades que buscaba satisfacer SUN

SUN realiza estudio de mercado en el que detecta un auge en el mercado de electrónica de consumo (como podían ser microondas, PDAs, televisores, etc.).

Además, observan que cada uno de estos dispositivos de consumo en particular tiene unos requerimientos de diseño únicos en lo referente a su hardware.

SUN buscaba un lenguaje de programación que pueda ejecutarse en cualquier dispositivo electrónico de consumo independientemente de cuáles fueran sus características del dispositivo a nivel hardware.

3.2) Investigando si ya existe un lenguaje que satisfaga dichas necesidades

Tras analizar los distintos lenguajes de programación ya existentes en el mercado, SUN, no encuentra ningún lenguaje que cubra al 100 % las necesidades que la compañía está buscando.

Aunque, sí que encuentra algunos lenguajes como C y C++, que se asemejan en parte a lo que se busca. Pero, con ellos no se puede realizar la tarea de realizar un software que fuera independiente de la arquitectura en la que se ejecuta. Ya que, requerían una compilación (distinta) para cada uno de dispositivo y además, no estaban enfocados hacía la electrónica de consumo.

3.3) Analizando el proceso de ejecución de un programa escrito en C o C++ para varias plataformas

Cuando escribimos un programa en C o C++ solamente puede ser ejecutado sobre la plataforma para la que se realiza la compilación.

Por tanto, si queremos ejecutarlo en Windows, debemos realizar una compilación para Windows, y si quisiéramos ejecutar el mismo programa en otra plataforma por ejemplo Linux, deberíamos de recompilar el programa para dicha plataforma, y estar compilando el programa constantemente para cada una de las plataformas.

3.4) Analizando que camino coger, si añadir nuevas características a C/C++ o crear un lenguaje nuevo

La idea inicial de Gosling era intentar modificar C/C ++ añadiendo y eliminando características a dicho lenguaje, pero tanto él como Bill Joy (uno de los fundadores de SUN) lo encontraron inadecuado.

Algunos de los motivos por los que se consideró inadecuado a C/C++ fueron:

  • Necesitaba demasiada memoria
  • La falta de recolección de basura, la cual ocasiona que fueran los programadores los tuvieran que administrar manualmente la memoria del sistema produciendo muchos errores, etc.

Por todo ello, se modificó su idea inicial de modificar C/C++ por la de crear un lenguaje nuevo desde 0. Y diseñó el lenguaje con la sintaxis basada en el estilo de C/C++ junto a la filosofía que buscaba SUN de “escribe una vez, ejecuta en cualquier lado”.

Un ejemplo de que pese a que Java es un lenguaje nuevo comparte muchas características con C y C++ es la siguiente frase de James Gosling:

“Java es C ++ sin pistolas, cuchillos y garrotes”. — James Gosling

3.5) Ejecución de un programa escrito en Java

Por todo lo comentado anteriormente, SUN decide desarrollar un lenguaje de programación heterogéneo (que se pueda ejecutar en cualquier hardware incluido los electrónicos de consumo) a partir de un solo bloque de código y tras solamente realizar 1 compilación.

El principal beneficio de que el lenguaje sea independiente de la plataforma a diferencia de C y C++ es que nos va a permitir poder realizar una sola compilación y ejecutar dicho programa en cualquier plataforma sin tener que recompilar el código para cada una de las plataformas.

El principal culpable de que podamos realizar la ejecución independiente de la plataforma (Linux, Windows…) es la Java Virtual Machine (o JVM). Ya que cada uno de las plataformas tiene una JVM específica que nos permitirá realizar la ejecución de los programas de Java en dicha plataforma.

4. SUN arranca el proyecto de creación de un nuevo lenguaje

4.1) SUN crea el proyecto Green Team

En 1991 SUN inicia el proyecto Green Team en el que junta a sus mejores ingenieros.

El objetivo del proyecto será el de desarrollar un lenguaje dirigido hacía dispositivos de electrónica de consumo principalmente los que no eran computadores.

El proyecto “Green Team” cuenta inicialmente con 3 integrantes:

  • James Gosling: También conocido como “el padre de Java” o “Dr. Java”. Gosling ostentaba inicialmente el cargo de líder técnico del proyecto, aunque más tarde, ya en 1984 fue vicepresidente de la compañía hasta el año 2010 en el que finalmente abandonó la compañía.

Gosling es considerado como el padre de Java principalmente debido a que fue el encargado de realizar la concepción y el desarrollo de la arquitectura del lenguaje de programación Java. Todo ello ha sido determinante para recibir numerosos premios como ser elegido miembro de la Academia Nacional de Ingeniería (NAE) en 2004. La idea de crear la máquina virtual se remonta a sus orígenes cuando era estudiante de un postgrado y creó una máquina virtual para que su profesor pudiera ejecutar programas escritos en UCSD Pascal.

  • Patrick Naughton: Patrick estaba tan frustrado con el estado de las herramientas y las APIs (interfaces de programación de aplicaciones) del proyecto con el que trabajaba en SUN. Que había decidió marchar a otra compañía y tras una propuesta de NeXT (una empresa cofundada por el fundador de Apple Steve Jobs). Tras comunicarlo a SUN, la compañía decidió ofrecerle trabajar en el proyecto para desarrollar un prometedor lenguaje de programación y al final éste decidió quedarse en SUN.

Finalmente en 1994, tras las malas relaciones de la compañía (SUN) con Microsoft debido en parte al intento de posicionar a Java como una herramienta clave para aplastar a Microsoft. Patrick se marchó de SUN para trabajar en Disney.

Un año después de marcharse de SUN, tras una entrevista para la revista Wired dejó además esta polémica frase para la historia:

“Hay formas más baratas de decirle ‘vete a la mier…’ a Bill Gates” — Naughton a la revista Wired en 1995.

Durante su etapa como trabajador de Disney produciría uno de los mayores escándalos para la empresa de dibujos animados tras ser detenido por el FBI por un escandalo pedófilo. Debido a que en su intentó de reclutar a chicas menores en un chat bajo el nombre de “Hotseattle” y finalmente fue detenido por el FBI prácticamente “con los pantalones bajados”.

  • Mike Sheridan: el último miembro inicial del Green Project era Mike Sheridan, Mike, se encargó en definir la estrategia de trabajo de Java y el desarrollo comercial junto a Eric Schmidt (que aunque no pertenecía al equipo), en ese momento Director de Tecnología de SUN.

El proyecto tenía 5 objetivos/propósitos principales:

  1. Debería usar la metodología de la programación orientada a objetos.
  2. Debería permitir la ejecución de un mismo programa en múltiples sistemas operativos.
  3. Debería incluir por defecto soporte para trabajo en red.
  4. Debería diseñarse para ejecutar código en sistemas remotos de forma segura.
  5. Debería ser fácil de usar y tomar lo mejor de otros lenguajes orientados a objetos, como C++.

4.2) El Green Team crece

Con el paso del tiempo, en 1997, el Green Team empieza a crecer y ya está formado por 16 integrantes.

Muestra de ello, es la siguiente fotografía de la 5ª Green BBQ (en la que pese a que no asistieron los 16 miembros del equipo) ya se ve claramente cómo ha aumentado el equipo.

El equipo compartirá el nombre, se autodenomina, bajo el mismo nombre que el proyecto “Green Team”

4.3) Green Talk, el nombre inicial de Java

Inicialmente, en sus orígenes, cuando SUN crea el lenguaje de programación que actualmente conocemos bajo Java, este, era conocido como Green Talk.

En aquel entonces, los archivos del lenguaje, tenían como extensión las iniciales del nombre del lenguaje .gt (de GreenTalk).

4.4) Green Talk cambia su nombre por OAK

Más tarde, en 1991, el lenguaje cambia de nombre (de Green Talk) a OAK (roble en inglés).

Algunos dicen que el principal motivo era en honor a un árbol que había junto a la oficina. Además, de por el significado que tiene un roble en muchas culturas como un símbolo de fuerza y que hace que sea elegido como árbol nacional de muchos países como Estados Unidos, Francia, Alemania, etc.

Por tanto, Green Talk pasa a llamarse OAK.

4.5) OAK, finalmente da paso a Java, el nombre actual del lenguaje

Tras la modificación del nombre inicial del lenguaje (de Green Talk a OAK), SUN se encuentra con el problema que al intentar registrar OAK como marca comercial, pero dicha marca ya está registrada por una empresa de hardware bajo el nombre de OAK Technology, Inc.

Tras encontrarse con este problema, finalmente, en 1995 y tras no poder registrar OAK como marca comercial, SUN decide cambiar el nombre del lenguaje de programación a Java. Ya que consideraron que volver al antiguo nombre (Green Talk) comercialmente no tenía demasiado “gancho”.

Actualmente, Java es el famoso nombre que continúa ostentando el lenguaje por lo que continúa siendo vigente actualmente.

4.6 ¿De donde surge el nombre de Java?

Existen varias hipótesis de porque definitivamente se decidió cambiar el nombre del lenguaje a Java. Las más famosas son:

  • Acrónimo Just Another Vague Acronym (“sólo otro acrónimo ambiguo más”).
  • Otras fuentes señalan que podría tratarse de las iniciales de sus creadores: James Gosling, Arthur Van Hoff y Andy Bechtolsheim.
  • Aunque la que más bombo tiene (y para mí la más creíble) es la de que Java, es una isla de Indonesia donde se produce café muy famoso conocido como “café de Java”. Por lo visto este tipo de café se vendía en una cafetería cercana a la oficina; de ahí su característico icono de una taza de café caliente.

4.7) The Java Server, Java en los Simpson

Hasta tal punto es famosa esta última anécdota que hasta Matt Groening dibujó el siguiente cibercafé durante un capítulo de los Simpson (Thirty Minutes Over Tokyo de la 10ª temporada):

5. Más historia/culturilla sobre Java

5.1) Presentando los términos WORE y WORA

Que Java como ya hemos visto permita su ejecución con una sola compilación permite a SUN presentar a dicho lenguaje bajo los eslóganes de:

  • WORE → Write Once Run Everywhere (Escribir una vez, ejecutar en todas partes)
  • WORA → Write Once Run Anywhere (Escribir una vez, ejecutar en cualquier lugar)

Ambos eslóganes vienen a decir algo similar a “Escribe una vez y corre en todos lados”. Con ello, podemos desarrollar una aplicación y ejecutarla en cualquier plataforma, por tanto Java es multiplataforma:

  • Linux, MAC, Windows…
  • Gracias a Java Virtual Machine.

5.2) Presentación de Star 7 ¿Fracasará OAK?

En 1992 SUN presenta una PDA (conocida como Star 7). Que destaca por tener una interfaz gráfica con un asistente en forma de muñeco llamado Duke.

Sin embargo, el mercado para dispositivos electrónicos inteligentes de uso doméstico no crece al ritmo que SUN había pronosticado y tampoco es tan rentable como se esperaba.

El proyecto, por tanto, pintaba a fracaso hasta llegar a un punto en el que se medio abandonó.

Solo un milagro podría hacer que el proyecto fuera un éxito. Y pusieron al equipo a buscar cómo reinventar /desarrollar nuevas estrategias que produjeran beneficios.

5.3) Surge el milagro el BOOM de internet y la creación del primer navegador basado en OAK

Durante los años 90, se produce el milagro que salva a Java, el BOOM de internet marcando como no el comienzo de una nueva generación de productos para cubrir estas necesidades.

A mediados de los 90 internet era tan grande, que SUN decide cambiar el enfoque hacía la web. Disputando el dominio que en aquel entonces tenía Microsoft en lo referente al desarrollo de software. Para ello, lanza el primer web Browser (navegador) escrito en OAK que inicialmente fue llamado WebRunner y años más tarde conocido como HotJava.

“Nos dimos cuenta de que podíamos construir un navegador realmente genial. Así que creamos un navegador “, dice Gosling.

5.4) Ejecución de Applets desde el navegador de SUN

El navegador Hot Java destacaba por ser el primer navegador compatible que puede ejecutar applets en el lenguaje de programación OAK (el que será el futuro Java).

Más tarde otros navegadores empiezan a introducir compatibilidad con los applets de Java en sus navegadores. Por ejemplo «La feliz coincidencia» fue que el mismo día Marc Andreessen, vicepresidente ejecutivo de Netscape (y creador de Mosaic) anunció que Java sería soportado en su navegador.

¿Qué es un Applet Java?

Un applet es un pequeño programa que debe ejecutarse bajo un navegador que soporte Java incrustándose/insertándose en un documento HTML (página web) permitiendo añadir elementos como animaciones y sonidos a la página web y permitiéndonos además crear programas que cualquier usuario puede ejecutar.

Uno de los requisitos para que los applets funcionen es tener instalado Java y que esté activado a través del explorador web.

Aunque los Applets actualmente están de desuso, es muy posible que si navegabais en aquel entonces en internet os suene ver visualizado una ventana de carga de un Applet como la siguiente:

5.5) La década de los 90, Java está en todos lados

A finales de la década de 1990, Java estaba en todos lados. Había traído multimedia a Internet y comenzó a crecer más allá de la Web, alimentando dispositivos de consumo (como teléfonos celulares), computadoras comerciales y financieras, e incluso en la computadora a bordo de los rovers de exploración de Marte de la NASA .

La NASA empleó el lenguaje Java para crear su programa Maestro encargado de controlar y pilotar el Mars Rover en su exploración por el planeta rojo

5.6) La burbuja de SUN “We put the dot in dot com”

Impulsada por las enérgicas ventas de sus servidores UltraSparc que eran irresistibles para los grandes sitios web de todo el mundo.

Se creó una especie de burbuja que SUN aprovechó sacando la famosa frase publicitaria “We put the dot in dot com” (Pusimos el punto en .com).

La cotización de SUN entre 1999–2001 alcanzó 200.000 millones de dólares en su punto máximo con un precio máximo de 247 dólares por acción.

A finales de 2001, la burbuja explotó y el precio de las acciones se había desplomado a 49 dólares por acción.

5.7) Características de Java

  • Simple: Java nace de una evolución de C y C++ en la que se reducen varios aspectos que podían incrementar su complejidad. Por tanto Java es fácil de usar
  • Portable (arquitectura neutral): ya que permite ejecutarse independientemente de la plataforma gracias a la JVM.
  • Orientado a Objetos (POO): Utiliza el paradigma de la programación orientado a objetos ¡Para Java prácticamente todo es un objeto!
  • Robusto: Chequea el código del programa durante el ciclo de desarrollo (si trabajamos con un IDE) y nuevamente posteriormente durante su compilación. Con la finalidad de verificar que no existan errores en el código de nuestro programa.
  • Distribuido: Proporciona una serie de librerías que nos otorgan la capacidad de realizar comunicaciones en red por ejemplo con el protocolo TCP/IP permitiéndonos acceder a ficheros o datos en red que están situados en otros equipos fácilmente.
  • Compilado y posteriormente Interpretado: Java se compila preparando los ficheros para posteriormente ser ejecutado en la JVM. Y finalmente una vez compilado se interpreta por la JVM.
  • Multitarea (Multihilo o Multithread): Permite la ejecución concurrente/paralela de varios procesos en nuestros programas (simultáneos /a la vez) mientras se ejecuta en un sistema operativo.

6. Ediciones o Tipos de Java: ME, SE, EE y FX

6.1) SUN subdivide Java en múltiples versiones

Debido a la popularidad que Java alcanzó, y con la finalidad de dividir el lenguaje en función del entorno que se ejecute, SUN creó distintas versiones de Java (más conocidas bajo el término de plataformas).

Cada una de estas plataformas nacen con distintos propósitos y están destinadas a ejecutar aplicaciones en un entorno en particular (doméstico, ordenadores personales u ordenadores empresariales/supercomputadoras).

Las plataformas son grandes marcos que brindan distintas posibilidades de desarrollo.

Ya hemos hablado de que Java es un lenguaje de programación. Pero además es multiplataforma, ya que puede ser ejecutado en varias plataformas (Windows, Linux, Macintosh…).

El éxito de Java precisamente ha consistido precisamente en no encerrarse en los navegadores y en abarcar varias plataformas.

6.2) Versiones ME, SE, EE de Java

Cada una de las plataformas de Java está destinada a un entorno, es decir, estará destinada a un tipo de dispositivos en particular en el que se ejecutan aplicaciones de Java.

Java nos proporciona 3 grandes plataformas (también conocidas como distribuciones o ediciones). Y son:

  • Java ME (o Java Micro Edition): destinado hacia el desarrollo de aplicaciones Java en pequeños dispositivos (móviles, bluetooth, televisores o reproductores blu-ray).
  • Java SE (o Java Standard Edition): destinado hacia el desarrollo de aplicaciones de escritorio en ordenadores personales (Windows, Linux, Macintosh).
  • Java EE (o Java Enterprise Edition): destinado hacía el desarrollo de aplicaciones distribuidas (cliente-servidor o con múltiples capas) como aplicaciones web, APIS, etc.

6.3) Versión FX de Java

Además de estás 3 plataformas de Java, inicialmente dentro de la plataforma Java SE existía JavaFX, un conjunto de módulos y componentes que tenía como finalidad el crear aplicaciones con interfaz gráfica.

JavaFX tiene como objetivo el crear RIAs applications (RIA = Rich Internet applications o Aplicaciones de Internet Enriquecidas) que no son nada más y nada menos que aplicaciones web que tienen la gran mayoría de características que tiene una aplicación tradicional de escritorio. Y nace con la finalidad de competir con alternativas como Flash (de Abobe) y Silverlight (de Microsoft).

James Gosling refiriéndose a JavaFX: “La mayoría de los lenguajes de script están orientados a las páginas web; éste (JavaFX) está orientado a las interfaces que son altamente animadas”.

Con el tiempo, tras la absorción de SUN por parte de Oracle (de la que hablaremos más detenidamente un poco más abajo); finalmente, Oracle decide extraer a Java FX de la plataforma Java SE y crear una plataforma independiente (separada de las 3 que hemos hablado anteriormente) para poder trabajar con Java FX.

7. SUN es absorbida (comprada) por Oracle

7.1) ¿Es Java software libre? La decisión inicial de SUN antes de la absorción de Oracle

Durante su existencia, SUN se ha posicionado a favor del software libre en varias ocasiones. Muestra de ello son los programas que desarrolló bajo la licencia OpenSource como son: MySQL, Solaris, OpenOffice, Java, NetBeans (IDE de Java)…

Otra acción que demuestra su posicionamiento a favor del software libre es que SUN publicó desde sus inicios el código de Java tal y como afirma J. Gosling en la siguiente afirmación “El código fuente de Java estaba disponible para todos desde el primer día que fue lanzado en 1995”.

A partir de 2006 se produce un hecho importante para una parte de los desarrolladores el “Java abierto”, aunque otra parte de ellos considera que no fue suficientemente lejos en el proceso. Ya que SUN publica las versiones Java SE 6 y 7 bajo una licencia GLP. Un tipo de licencia permitía revisar internamente, aunque no redistribuir.

Con ello, SUN buscaba que la comunidad ayudase en el análisis de la seguridad, el reporte de bugs, mejoras en rendimiento, etc. Pese a que fue un éxito, tal y como reconoció Gosling, “No era lo suficientemente abierto para el público Open Source”. Y podemos afirmar que Gosling se quedó con ganas de más.

7.2) Oracle compra/absorbe a SUN

En 2009 Oracle compra a SUN por la escalofriante cifra de 7400 millones de dólares.

7.3) La compra de SUN por parte de Oracle provoca un cambio en la filosofía de Java produciendo la conocida como “fuga de cerebros”

Gosling se baja del barco, y abandona Oracle. Tan solo 6 meses después de que el gigante comprará a SUN. No expuso los motivos públicamente, pero eso sí, comentó que lo hace debido a qué literalmente “harían más mal que bien”.

Además de Gosling, también abandonaron Oracle varias personas relevantes como son: Jonathan Schwaztz (CEO), Scott McNealy y Tim Bray en lo que se conoce como la “fuga de cerebros de SUN”.

7.4) ¿Es Java software libre? La decisión de Oracle después de la compra de SUN

A partir de la versión 9 de JDK (Java SE 9) en adelante, y tras la absorción de SUN por parte de Oracle, se produzco un cambió en su política con el fin de requerir una licencia únicamente si su eso es para software comercial. Me imagino que con la finalidad de recuperar los 7400 millones de la inversión de la compra de SUN.

En Java, tanto el propio lenguaje como las APIs no tienen derechos de autor, pero una parte del JDK (la classpath) si. Esto es posible debido a que a pesar de que JDK (con excepción del classpath) es OpenSource (con licencia GLP). Oracle, mantiene los derechos de autor de una parte de Java.

→ ¿Entonces tengo que pagar por una licencia? Depende, la respuesta es sí y a la vez no.

→ ¿Para qué voy a utilizar mi software? ¿Uso comercial o uso no comercial (personal)? Si es a nivel no comercial podemos utilizar JDK sin problema.

En caso de usarlo a nivel empresarial tenemos varias opciones:

  • Utilizar JDK de Oracle en una versión inferior a la 9. Por ejemplo Java SE 8 que es LTS (sin coste alguno ya que es la última versión que no necesita licencia de pago).
  • Utilizar una versión de JDK superior o igual a la 9. Por ejemplo Java SE 11 que también es LTS (bajo una licencia de Oracle).
  • Otra opción sería utilizar una distribución abierta (open) de JDK. Por ejemplo: OpenJDK.

7.5) En 2020, Java celebra su 25 aniversario

Desde 1995, en 2020 Java cumple su 25º aniversario. Y continúa cumpliendo años y rumbo a los 50 años. Qué mejor manera de hacerse mayor que seguir presente y siendo un referente a tener en cuenta para muchos desarrollos actuales.

8. Entornos de ejecución de Java: JRE vs JDK

8.1) ¿Qué es JRE? ¿Qué es JDK? Y diferencias entre JRE y JDK

Para poder ejecutar programas en Java necesitamos instalar uno de los dos entornos de ejecución de programas Java. Utilizar una u otra dependerá principalmente del propósito que tengamos. Vamos a verlo más detalladamente:

  • Java Runtime Environment (JRE): está enfocado a usuarios finales que simplemente quieren ejecutar programas en Java (No para desarrollarlos). Y contiene solamente las partes de la plataforma Java SE necesarias para ejecutar programas Java. Pero no las que nos permiten realizar desarrollos.
  • Java Development Kit (JDK): está enfocado a desarrolladores de software e incluye las herramientas necesarias de desarrollo, el compilador de Java, el debugger, etc.

Por tanto en resumen:

  • JRE = JVM + librerías
  • JDK = JRE (JVM + librerías)+ Development Tools (como puede ser por ejemplo el compilador, debbuger, etc.)

Nosotros, vamos a crear programas, por tanto, instalaremos JDK ya que aparte de ejecutar programas en Java los vamos a desarrollar.

8.2) Historia de JDK

Durante 1995 aparece la primera versión de JDK una versión BETA (que por el momento no se lanza al mercado, por lo que, no estaba disponible para su descarga).

En 1996, SUN realiza el primer release (lanzamiento) oficial de Java concretamente la versión de JDK 1.0.

JDK son las iniciales de Java Development Kit que como ya hemos dicho simplemente es el Kit de desarrollo necesario para poder crear aplicaciones en JAVA.

8.3) Cambio de nomenclaturas de JDK a lo largo de la historia

La nomenclatura con la que nos referimos a las distintas versiones de Java se ha modificado en varias ocasiones a lo largo del tiempo.

Desde esta primera versión de JDK (JDK 1.0), Java ha ido adaptándose/evolucionando constantemente para cubrir nuevas necesidades que surgen en el mercado añadiendo mejoras, nuevas características y funcionalidades, etc.

Inicialmente las versiones de Java se conocían como JDK junto al número de versión (por ejemplo JDK 1.0 o JDK 1.1) y estaban englobadas en lo que se conocía como Java 1 (es decir la Java 1 Platform).

Más tarde, a partir de la versión 1.1 de JDK en adelante y hasta la versión J2SE 5.0, las siguientes versiones de JDK serán recogidas bajo la denominación/plataforma de “Java 2” (de Java 2 Platform). Junto a “SE” (de Standard Edition) con la finalidad de diferenciar las plataformas Enterprise Edition (Java EE) y Micro Edition (Java ME).

Si combinamos el J2 (de la plataforma) junto al SE (de Standard Edition) tenemos la nueva nomenclatura para las nuevas versiones de JDK las J2SE (Java 2 Platform, Standard Edition) junto al nombre de la versión de JDK.

J2 + SE = J2SE

El “2” originalmente tenía la intención de enfatizar los principales cambios introducidos en la versión 1.2, las versiones del JDK anteriores a 1.2 (es decir, 1.0 y 1.1) no son Java 2. El “SE” se utiliza para distinguir la plataforma base de las plataformas Enterprise Edition ( Java EE ) y Standard.

En 2006, nos encontramos con otro cambio de nomenclatura, el conocido ya por todos nosotros “J2SE” desaparece y cambia su nombre a Java SE (Java Standard Edition). Además del cambio de nombre, podemos comprobar que también se elimina el .X (cero) de las versiones.

8.4) Frecuencia de lanzamiento y tipos de versiones de JDK: antiguas, LTS, actual y futuras versiones

En sus inicios algunas versiones han introducido más cambios que otras y por tanto, se suelen considerar como versiones importantes.

Principalmente el factor que principalmente más a determinado el volumen cambios que se introducen en una versión de JDK ha sido el tiempo que pasa entre el lanzamiento de una versión y la siguiente versión, ya que cuanto más tiempo entre versión y versión más novedades, por tanto, el tiempo puede ser un indicador importante para hacernos una idea de cuales son las versiones con más cambios; aunque lo correcto sería verificarlo mirando los cambios introducidos en dicha versión.

Si nos fijamos, en los ciclos de lanzamientos versiones hay que destacar que en sus primeras versiones, los ciclos de lanzamiento de Java eran anuales. Más tarde estos ciclos entre versión y versión se fueron alargando a más 1 año , ¡Llegando incluso a pasar de 3 a 5 años entre lanzamiento y lanzamiento!

Actualmente y desde la versión 9 de JDK (la Java SE 9), las nuevas versiones se lanzan cada 6 meses (en marzo y septiembre).

Dentro de las versiones de JDK podemos clasificarlas en:

  • Versiones antiguas (las rojas y amarillas): Son versiones antiguas del Java Development Kit que pueden seguir siendo usadas, de hecho es muy normal que si trabajamos en una empresa podamos trabajar con la versión 8 de JDK, etc. La gran mayoría de ellas a excepción de alguna LTS (las vemos justo debajo) ya han perdido el soporte por parte de Oracle.
  • Versiones LTS (las amarillas): Con LTS nos referimos a Long Time Support, son versiones a las que Oracle les da soporte a largo plazo Oracle. Por tanto, garantiza soporte y actualizaciones para este tipo de versiones durante como mínimo 3 años, en lugar de tan solo 6 meses.
  • Versión actual (la verde): es la última versión publicada por Oracle
  • Versiones futuras (las azules): son versiones de JDK que se lanzarán en un futuro (marzo o septiembre).

Entre todas las versiones, si podríamos destacar algunas son las que tienen soporte y son:

  • La actual, por ser la última versión publicada por Oracle (6 meses a excepción de que se trate de que la última versión sea LTS)
  • Y también las LTS porque durante un tiempo determinado reciben soporte (como mínimo 3 años)
  • JDK 8 por ser la última versión gratuita que no requiere licencia para su uso comercial.

8.5) Oracle JDK vs OpenJDK diferencias

OpenJDK es una versión de la plataforma Java en Open Source (por tanto completamente de código abierto) con una licencia GNU.

Oracle JDK a partir de la versión 8 de JDK, por tanto desde la versión 9 de JDK se requiere una licencia comercial en virtud del Acuerdo de licencia de código binario de Oracle. Si usamos Oracle JDK, recibiremos actualizaciones de software por parte de Oracle.

  • Por ejemplo, si surge un problema de seguridad, se parcheará y lanzará una actualización, y se asegurará por tanto que todos sus actualizadores automáticos y demás lo recojan, y le enviarán un correo electrónico al respecto, etc.

Históricamente, Oracle JDK ha tenido un mejor rendimiento que OpenJDK. Sin embargo, el rendimiento de OpenJDK está mejorando bastante gracias a la contribución de la comunidad OpenJDK. Además hay que destacar que Microsoft está preparando su propia compilación de OpenJDK, una distribución de código abierto Java disponible gratuitamente que además tendrá soporte a largo plazo.

9. La disputa de la década, el juicio que enfrenta a Oracle VS Google

9.1) Google rompe relaciones con Oracle y Java por la disputa de la década en la que Oracle se enfrenta a Google

Hasta 2010, Java era el lenguaje principal con el que se desarrollaban aplicaciones para el principal sistema operativo Android.

En 2010, Oracle denunció a Google reclamándole nada más y nada menos que 9.000 millones de dólares tanto por los daños sufridos como por los beneficios que obtuvo Google gracias a Android.

Oracle se basa en que se ha efectuado una violación de patentes y de la propiedad intelectual alegando que Google copió ilegalmente más de 11.000 líneas de código de la API de Java para desarrollar su sistema operativo Android sobre las Oracle reclama sus derechos de autor.

Lo que les dio a los desarrolladores una superficie de API familiar para programar y dar un impulso a su entorno en ese momento. Aunque no se copió ningún código del Open JDK (que está licenciado bajo la GPL), Oracle había argumentado que su definición de API estaba protegida por derechos de autor y, por lo tanto, que Google tenía la culpa de copiar las definiciones incluso si no copiaba el código fuente directamente.

Tras la denuncia Google movió rompiendo las relaciones con Oracle y decide mover ficha declarando a Kotlin su lenguaje de programación preferido para el desarrollo de aplicaciones Android.

9.2) Veredicto final, gana Google

Después de más de una década en los tribunales y tras tres juicios y dos apelaciones, finalmente la corte suprema de los Estados Unidos de América ha declarado que el uso de la API de Java por parte de Google fue un uso legítimo. Confirmando la sentencia que la copia de Java en Android fue un “uso justo” y por tanto, evitando a la compañía tener que indemnizar con más de 9.000 millones de dólares a Oracle.

9.3) Gosling da su opinión sobre la disputa

“Si bien tengo diferencias con Oracle, en este caso están en lo correcto. Google engañó totalmente a Sun. Todos estábamos realmente perturbados, incluso Jonathan[Schwartz] (CEO SUN): simplemente decidió poner una cara feliz y trató de convertir los limones en limonada, lo que molestó a mucha gente en Sun “.

Pese a ello, Gosling aprobó la decisión del tribunal tomada por la corte suprema en la que las API no deben ser protegidas por derechos de autor.

10. Entendiendo los sistemas de numeración

Existen muchos sistemas de numeración, en este apartado vamos a enfocarnos únicamente en hablar sobre los que nos permitirán entender Java y son:

10.1) Sistema de numeración decimal:

El más famoso y habitual para nosotros ya que lo utilizamos habitualmente en nuestro día a día para realizar cálculos como por ejemplo: contar (0, 1, 2, 3…).

10.2) Sistema de numeración binario (base 2):

El sistema binario (base 2), consiste en un sistema de numeración en el que los números se representan utilizando solamente las cifras cero y uno (0 y 1).

Podemos decir que es el lenguaje de los ordenadores ya que es el lenguaje que entienden/“hablan” computadoras, y por tanto, si queremos comunicarnos con los componentes de nuestra computadora dichas instrucciones tendrán que llegar a nuestros equipos en sistema binario.

Este sistema realmente trabaja internamente con dos niveles de voltaje (presencia de voltaje 1, ausencia de voltaje 0).

Un ejemplo muy simple de comunicación binaria podría ser las luces de una atracción de feria o las luces de navidad. En la que el 0 representa ausencia de electricidad y por tanto; no se iluminarán. Y el 1 presencia de electricidad y por tanto, se iluminarán.

10.3) ¿Qué es un bit? Conociendo la unidad mínima de la informática

Un bit (la unidad mínima de informática) y solo puede almacenar en su interior un valor binario 0 o 1.

Debido a que un solo bit solo puede almacenar dos valores, los bits se combinan en unidades grandes para contener un rango mayor de valores.

Por tanto, la combinación varios bits (es decir, de 0 y 1) darán como posible resultado múltiples combinaciones (conocidas como puertas lógicas) que nos permitirá comunicarnos con el hardware del dispositivo.

La palabra bit proviene del término BInary digiT.

10.4) Unidades superiores al bit: Nibble, byte y word

Los bits se pueden agrupar entre otros en:

  • Nibble: equivale a 4 bits
  • Byte: equivale a 8 bits
  • Word: equivale a 16 bits (o 2 bytes).

10.5) Entendiendo el significado de la base en el sistema binario

El funcionamiento del binario consiste en ir elevando su base (base 2) a la X

2^X donde X es un valor numérico que va incrementándose y que inicialmente siempre empieza por 0. Por ejemplo:

  • 2=0
  • 2¹ = 2
  • 2² = 4…

Cuando elevamos el siguiente número dicho número se sitúa siempre en el lado izquierdo y vale el doble que el anterior.

Finalmente sumamos los valores correspondientes a las potencias de cada uno de los números (solo los que tengan como valor un 1) sin importar la dirección por la que empezamos (de izquierda a derecha o viceversa). Aunque sí que se aconseja empezar de derecha a izquierda ya que así sabremos que el número de la izquierda vale el doble que el de la derecha.

Un ejemplo visual de todo esto podría ser:

10.6) Ejercicios de conversión de decimal a binario:

Os dejo unos simple ejercicios para que podáis practicarlo un poco, aunque la finalidad simplemente es entenderlo y se podría profundizar mucho en ello (realizando sumas, restas, etc.) pero no es la intención de este artículo:

10.7) Binarios firmados MSB y LSB

En matemáticas, los números están formados por un signo y un valor en el que indicamos si el valor de dicho número es positivo (entre los que se incluye el 0) o negativo. Por ejemplo: +321, -523, 632…

Y también si son pares o impares. Por ejemplo: 120 (par), 323 (impar)…

Pero cuando realizamos una transmisión de datos (es decir, una comunicación/transferencia) en lo referente a la computación.

Dichas comunicaciones involucran un gran número de bits, es decir, no enviamos un solo bit sino que por ejemplo utilizamos grupos de 8 bits (1 byte) o otras unidades.

Para que el ordenador sea capaz de entender si un número es positivo o negativo o si es par o impar tenemos que utilizar los MSB o LSB.

  • MSB → Most Significant Bit (el bit más a la izquierda) decide si el número será positivo o negativo. Vamos a ver un ejemplo:

Por tanto, si trabajamos sobre un byte (8 bits), un byte, Y le restamos el bit que define el símbolo (MSB), nos quedan 7 bits.

8 bits — 1 byte de símbolo (MSB) = 7 bits disponibles

Si elevamos la base binaria hasta la 7, 2⁷, obtenemos un total de 256 combinaciones posibles. La mitad de estas combinaciones serán positivas (del 1 al 128) y la otra mitad negativas (del 0 al -127).

  • LSB → Least Significant Bit (el bit más a la derecha) decide si el número será par(0) o impar(1).

Para poder trabajar con un MSB es necesario trabajar con varios bits (mínimo dos) uno con el valor (el LSB) y otro con el símbolo(MSB)

10.8) Entendiendo el funcionamiento de la comunicación en binario

Si queremos escribir hola en binario necesitamos utilizar una codificación.

Hay muchos códigos (reglas de codificación) diferentes. Uno de los más conocido es:

  • ASCII (American Standard Code for Information Interchange) este sistema utiliza 8 bits (1 byte) para su codificación.

Aquí vemos cómo se representan algunos caracteres del alfabeto en binario en la codificación ASCII:

Si por ejemplo, vamos a una web que nos realiza la conversión de binario a ASCII como la siguiente: https://www.convertbinary.com/to-text/ podemos ver que cuando nosotros pulsamos la tecla A realmente el ordenador internamente (si trabaja con la codificación ASCII) está utilizando 01000001 para identificar a dicho carácter.

Por tanto, por ejemplo para escribir HOLA (con mayúsculas ya que con minúsculas sería diferente) en binario necesitamos 4 bytes (32 bits):

Podemos verificarlo utilizando la tecla ALT + el valor del número en decimal al que equivale el valor en binario.

  • Alt + 72 = H
  • Alt + 95 = O
  • Alt + 76 = L
  • Alt + 65 = A

Para poder sacar el número en decimal, podemos utilizar la calculadora de Windows en vez de la tabla que hemos usado hasta ahora de la siguiente manera:

Es muy importante situarse sobre BIN haciendo doble clic para indicarle a la calculadora que vamos a introducir un número del sistema binario.

10.9) Sistema Octal (base 8):

El sistema octal(base 8), consiste en un sistema de numeración en el que los números se representan utilizando los números del 0 al 7.

Y nos permite representar números en binario de forma abreviada.

Vamos a ver un ejemplo:

10.10) Sistema Hexadecimal (base 16):

El sistema hexadecimal (base 16) se trata de un esquema alternativo al sistema decimal y al binario. También nos permite representar números en binario de forma abreviada.

Este sistema está representado en sus 9 primeros dígitos en numeración decimal, junto a las letras del alfabeto del A a la F (cada una de estas letras tiene su equivalencia en binario del 10 al 15).

  • 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A=10, B=11, C=12, D=13, E=14 y F=15

En el sistema hexadecimal cada valor (del 1 al F) corresponde a un nibble (es decir, a 4 bits). Por tanto, este sistema trabaja sobre la unidad intermedia entre el bit y el byte, el nibble (4 bits).

1 byte = 2 nibbles = 8 bits.

Si nos fijamos en el valor binario de los números hexadecimales van de 0000 (0) al 1111 (F = 15).

Un poco más abajo, cuando expliquemos el proceso de compilación de un programa en Java y lleguemos al bytecode, entenderéis el porqué os he explicado todos estos sistemas de numeración.

11. Configurando e instalado el Kit de Desarrollo (JDK) para poder desarrollar con Java

Para instalar JDK tenemos que ir a la web oficial de Oracle, o en el caso de instalar un OpenJDK a la web de la distribución.

En mi caso instalaré dos versiones, la última versión de JDK (y por tanto, la actual) y la versión 8 de JDK. Para que veáis que podemos tener varias versiones de JDK conviviendo en nuestro sistema.

11.1) Instalando la última versión de JDK

Para descargar la última versión de JDK, buscaré en Google java jdk lastest version

Lo que me llevará a la web de Oracle desde la cual podremos descargar la última versión pulsando sobre JDK Download:

Y seleccionamos la versión a JDK a instalar, en mi caso al ser un equipo Windows descargaré el instalado Windows x64 Installer:

Una vez descargada, lo ejecutamos y como cualquier otra instalación realizamos el famoso siguiente siguiente…

Os aconsejo no tocar la ruta por defecto:

11.2) Instalando JDK 8, la última versión LTS gratuita para uso comercial

Y ahora realizamos lo mismo con la versión 8 de JDK:

Es posible que la versión 8 de JDK os obligue a crear una cuenta de Oracle para poder realizar la descarga. Pero no os preocupéis ya que es totalmente gratuita.

En la versión 8 de JDK no se instalarán junto JDK y JRE sino que se hacen dos instalaciones separadas en dos directorios separados:

Si ahora desde el CMD hacemos un where java, vemos que nos aparece el directorio sobre el que tenemos instalado Java:

Si vamos a dicho directorio, vemos que tenemos las dos versiones de JDK instaladas la JDK 16 y la JDK 8 junto a su JRE que al ser una versión algo más antigua, se instala en un directorio aparte del JDK:

11.3) ¿Por qué configuramos las variables de entorno en Java?

Si intentamos mostrar la versión de java desde el CMD y no nos da el siguiente resultado, tenemos que configurar las variables de entorno:

  • Si el resultado es OK, y por tanto, tenemos correctamente configuradas las variables de entorno el resultado será:

En este caso, al haber instalado la versión 16 de JDK primeramente, se nos han configurado las variables con dicha versión de JDK.

  • Resultado KO, y por tanto, no tenemos correctamente configuradas las variables de entorno el resultado será:

Pese a ello, Java funciona correctamente pero al no tener la variables de entorno correctamente configuradas solamente lo podemos ejecutar desde la ruta donde se encuentran los archivos de java. Vamos a ver un ejemplo que demuestra que si que funciona:

Si visitamos otro directorio que no sea el donde se encuentran los ficheros de Java y ejecutamos java -version no nos funcionará:

11.4) Configurando las variables de entorno (Path)

Configurar las variables de entorno nos va a permitir el poder trabajar con java desde cualquier ruta de nuestro sistema.

Para configurar las variables de entorno, escribimos, path en el buscador de Windows:

Y una vez abierto el editor de variables de entorno del sistema vamos a Variables de entorno:

Y vemos que tenemos dos apartados:

  • El apartado de usuario (en mi caso David)
  • El apartado del sistema global

Dependiendo de donde configuremos las variables de entorno afectarán a nuestro usuario solamente o a todos los usuarios del sistema.

Al tratarse de un ordenador personal, yo las instalaré en el apartado inferior, el global.

Tenemos que configurar dos variables de entorno:

  • JAVA_HOME → contendrá la ruta raíz de la carpeta de la instalación de la versión de JDK
  • PATH → contendrá la ruta de la carpeta BIN situada en el interior de la ruta raíz de la versión de JDK

Si queremos configurar esta versión de JDK realizaremos lo siguiente:

  • JAVA_HOME → C:\Program Files\Java\jdk-16.0.2

Y ya tendríamos la variable JAVA_HOME apuntando a la ruta raíz de la versión de JDK:

  • PATH → C:\Program Files\Java\%JAVA_HOME%\bin o bien utilizar la versión en específico sin utilizar la variable Java_Home C:\Program Files\Java\jdk-16.0.2\bin

Aunque podemos hacer lo siguiente: C:\Program Files\Java\jdk-16.0.2\bin:

Se aconseja subir dicha variable de entorno arriba del todo ya que en algunas ocasiones pueden existir algunas configuraciones que pueden dar problemas.

Es muy importante cerrar cualquier CMD que tengamos abierto antes de haber configurado las variables de entorno ya que no sino dicha terminal no detectará las modificaciones. Si abrimos una nueva terminal podemos ver que nos funciona correctamente:

Si quisiéramos cambiar la versión de JDK, de forma manual, tendríamos que modificar las dos variables. Por tanto, se aconseja pasar la ruta de la variable de entorno raíz y así nos evitamos modificar la ruta de dicha variable:

Si volvemos a testear, nos funciona correctamente:

11.5) Cambiando la versión de Java sobre la que vamos a trabajar de forma manual

Si quisiéramos cambiar la versión solamente tendríamos que modificar la versión a la que apuntamos en la variable de entorno JAVA_HOME

Si ahora hacemos un Java -version podemos ver que ya podemos desarrollar para la versión 8 de JDK:

En nuestro caso dejaremos la versión 16 de la JDK :

11.6) ¿Por qué algunas versiones de Java se denominan 1.X y otras utilizan otra nomenclatura?

  • Anteriormente y para confirmar la instalación de Java y su correcta ejecución desde cualquier ruta del sistema hemos ejecutado el comando java –version
  • Las versiones de Java inferiores a la 9 simplemente tenían un esquema de nomenclatura diferente que es el 1.X donde X era la versión de Java. Por ejemplo, si instalamos Java 8 cuando hacíamos un java –version nos mostraba 1.8. Esto simplemente significa que tenemos el sistema configurado para trabajar con la versión Java 8
  • Con el tiempo, y a partir de la versión 9 de Java, el esquema de nomenclaturas de versiones cambió, y las versiones de Java ya no tienen el prefijo 1.x. Ahora, si trabajamos por ejemplo sobre la versión 15 nos mostrará la versión directamente

12. Compilación manual de un programa en Java y funcionamiento de la JVM

12.1) Analizando el proceso de compilación de un programa en Java

Cuando escribimos un programa en Java generamos lo que se conocen como clases. Una clase es un archivo con extensión (que terminan en) .java con instrucciones que como ya dijimos durante este artículo son de alto nivel. Y por tanto, estos ficheros al contener instrucciones escritas en alto nivel, y no en binario, por el momento no son legibles ni por el sistema operativo ni por el hardware (los componentes) de nuestros ordenadores.

¿Cómo hacemos que estos ficheros sean leídos por la JVM? Pues realizando una compilación que transformará los archivos con extensión .java a unos archivos con extensión .class. En dicha compilación, además las instrucciones escritas en alto nivel se transforman a byte code (un lenguaje intermedio entre nuestras instrucciones en alto nivel y el lenguaje binario) que finalmente tras ser interpretado (“leído”) por la JVM se ejecutarán en nuestros dispositivos independientemente del sistema operativo sobre el que se ejecute (Linux, Windows, Mac) y del hardware (los componentes/piezas) del dispositivo.

12.2) ¿Qué es Java Virtual Machine (JVM)? ¿Qué relación tiene con bytecode?

Tanto el entorno de ejecución JRE como el entorno de ejecución JDK contienen internamente la Java Virtual Machine (más conocida como JVM).

La Java Virtual Machine es la encargada de pasar el archivo de Java a bytecode para que finalmente este sea ejecutado por JIT y finalmente transformado a lenguaje binario para que la máquina sea capaz de interpretar las instrucciones que hemos escrito en alto nivel.

12.3) JAVA y JVM son inseparables pero la JVM también tiene capacidad de ejecutar otros lenguajes

Aunque Java y la JVM por decir de alguna manera “son inseparables”, es decir, “van de la mano” ya que la JVM ejecuta código de Java y por tanto, están estrechamente emparejadas. A su vez, ambas también están perfectamente separadas.

Ya que también existen otros lenguajes que están diseñados específicamente para ejecutarse mediante a la JVM, como son: Groovy, Scala o Kotlin. Y por tanto, me gustaría destacar que la JVM no es solamente/exclusivamente para ejecutar programas de Java.

12.4) ¿Qué es el Just-In-Time Compiler (JIT)?

SUN, nos proporciona a la Java Virtual Machine (JVM) que tras haber realizado la compilación a bytecode, internamente ejecuta el código en bytecode gracias al JIT (Just-In-Time compiler).

JIT, por tanto, nos permitirá traducir el bytecode a código nativo (binario) para que finalmente sea interpretado por nuestro SO y posteriormente por nuestro hardware.

Para ayudarnos a entender mejor el proceso, vamos a visualizar el siguiente esquema:

La clave del poder “Escribir una vez, ejecutar en todas partes” de Java (WORA/WORE) es bytecode.

13. Compilación y descompilación manual en Java (sin IDE)

13.1) Realizando nuestra primera compilación de un programa Java de forma manual (sin IDE)

Para ello, debemos crear un archivo con extensión .java con el nombre HelloWorld y en su interior vamos a crear una clase llamada bajo el mismo nombre HelloWorld. Ya que en Java todo debe de estar contenido dentro de una clase. Vamos a ver un ejemplo:

Es muy importante que tengamos visible las extensiones de los ficheros en nuestro sistema:

Ya que sino si creamos un archivo .txt para modificarlo a .java podemos ver que cuando marcamos dicho check finaliza en .txt y para Windows es un fichero de texto y no de Java:

Si os pasa esto, simplemente tenéis que eliminar el .txt del nombre del fichero y ahora sí que será un fichero Java:

Una vez creada la clase vamos a crear el método main que si lo traducimos del inglés viene a decir algo así como principal y dicho método será el primer método (“parte del programa”) que se ejecuté en nuestro programa. Vamos a verlo:

Y finalmente, tenemos que añadir las instrucciones mediante a las que le indicaremos que queremos que haga nuestro programa. En mi caso, el mostrar un mensaje por la consola de Hola Mundo mediante la instrucción System.out.println(“Hello World”). Vamos a verlo:

Todas las instrucciones de Java deben acabar con un ;

Una vez creado el programa en Java, tenemos que ir a la ruta sobre la que hemos creado el programa, en mi caso el escritorio y realizar la compilación del programa mediante el comando javac:

Dicho comando nos ha generado el fichero HelloWorld.class en bytecode (un lenguaje intermedio entre lenguaje de alto nivel y lenguaje binario).

Y finalmente, una vez generado el fichero con extensión .class en bytecode, ya podemos realizar la ejecución de dicho fichero desde la Java Virtual Machine (JVM). Para ello, utilizamos el comando java sin poner la extensión .class del fichero. Vamos a verlo:

13.2) Repasando el proceso de compilación desde un esquema

Por tanto si os fijáis hemos pasado por todos los pasos de la siguiente imagen:

13.3) Desmenuzando el funcionamiento de la JVM

Si nos fijamos, el JVM internamente carga las clases mediante a class loader el cual transformar el código a nativo (lenguaje binario) para posteriormente llamar al Execution Engine y posteriormente hacer una llamada al método Nativo para ejecutar el código de nuestro programa en Java en función del sistema operativo y la arquitectura y llegando finalmente al hardware de nuestro dispositivo.

13.4) Explicando la característica Key Sensitive de Java y realizando una compilación incorrecta (con errores)

Hasta ahora hemos realizado una compilación exitosamente pero ¿Qué pasaría si por ejemplo modificamos la primera S en mayúscula de System.out.prinlnt a una en minúscula y realizáramos nuevamente una compilación?

Cuando hacemos la compilación vemos que el compilador nos arroja un error:

Esto es debido a que java es Key Sensitive, es decir, que detecta entre las mayúsculas y las minúsculas. Este error lo podemos solucionar muy fácilmente, tan solo poniendo la S en mayúsculas y volviendo a compilar:

14. Descompilación manual/automática de un archivo en bytecode, transformación de bytecode a hexadecimal e historia de CAFEBABE

14.1) Realizando una descompilación manual de un archivo ya compilado a bytecode (archivo con extensión .class)

Usualmente cuando realizamos una compilación de un programa en Java tenemos dos ficheros. En el caso de la compilación anterior, para ser más exactos teníamos:

  • HelloWorld.java: contiene el código escrito en Java de nuestro programa.
  • HelloWorld.class: contiene el código del programa en Java en formato bytecode

Si por error eliminamos el archivo HelloWorld.java, habríamos perdido el código fuente original de Java. Y por tanto, solamente tendríamos nuestro código en formato bytecode:

Si quisiéramos modificar nuestro programa, nos encontraríamos ante el problema de que no podemos introducir instrucciones de Java en dicho código ya que está escrito en bytecode. Pero existe una forma de “recuperar” gran parte de nuestro código:

Para ello, debemos realizar una descompilación o un desamblamiento del fichero Java:

Para realizar dicha descompilación utilizamos el comando javap lo que nos arrojará algo similar al código original que teníamos:

Fichero original:

Otra opción es añadir el el parámetro -c para obtener algo más de información al respecto:

Aunque si comparamos este código con el original, podemos observar que con este proceso de desamblado no podemos recuperar todo el código al 100 %.

14.2) Desamblado de un fichero con un software especializado (Java Decompiler)

Para realizar un desamblado más similar al código original, es aconsejable utilizar un software especializado en ello, ya que utiliza varios parámetros para ello y el resultado será mucho más similar. Para ello descargamos la versión JD-GUI compatible con nuestro sistema operativo, abrimos el archivo y ¡Tachan! Como si de magia se tratará, ya tenemos el archivo original.

El programa inicialmente para que funcione debe abrir una clase .java, por lo que podemos crear una vacía ya que la original no la tenemos:

Y una vez abierto, seleccionamos el archivo HelloWorld.class y podemos observar que aunque con alguna leve modificación tenemos el programa original al completo:

Explicando bytecode, convirtiéndolo bytecode a hexadecimal y la historia de CAFEBABE y CAFEDEAD

14.3) Convirtiendo el código del fichero .class (bytecode) a hexadecimal

Si abrimos los ficheros HelloWorld.java y HelloWorld.class desde el bloc de notas podemos ver que tenemos dos resultados completamente diferentes:

  • HelloWorld.java: está escrito en un lenguaje de alto nivel y por tanto entendible por nosotros.
  • HelloWorld.class: en cambio, está escrito en bytecode, un lenguaje intermedio entre Java (alto nivel) y binario.

En realidad este código que estamos viendo en el archivo HelloWorld.class, es código en bytecode que podemos convertir en hexadecimal, mediante un conversor.

En este caso, trabajaremos con HxD Hex Editor (aquí tenéis la web) un software especial para ello (aunque con que veáis la foto lo entenderéis perfectamente):

Bien vamos a explicarlo un poco mejor, un byte está compuesto por 8 bits (byte = 8bits) y un dígito en hexadecimal representa (4bits) por lo tanto (4bits+4bits=8bits = 1 byte). En valor binario la representación sería desde 00000000 a 11111111 y en hexadecimal en cambio de 00 a FF. Si nos fijamos, el lenguaje hexadecimal usualmente está separando bloques de un byte.

14.4) ¿Qué son los números mágicos (magic numbers) en la programación?

Los números mágicos, son el mecanismo que permite identificar al sistema operativo o a una aplicación que tipo de archivo vamos a ejecutar desde detrás de la escena con el fin de identificar/determina si por ejemplo si puede leer el fichero, si es compatible, el tipo de fichero que se va a intentar abrir... Puede utilizar los 32 primeros bits, como indicador del tipo de archivo que se trata.

Esto se realiza mediante los 32 bits iniciales de un archivo (es decir, mediante a los 4 primeros bytes de este).

La gran mayoría de lenguajes de programación utilizan un tipo de 32 bits (es decir, 4 bytes), con la finalidad de representar ciertos tipos de datos detrás de la escena y bytecode también lo utiliza. Estos bits, pueden ser representados en decimal, formato hexadecimal, etc. Por ejemplo, un fichero en pdf puede empezar por el valor hexadecimal 25504446, vamos a ver un ejemplo:

Si utilizamos un lector de ficheros comprimidos y queremos leer un fichero con extensión .ZIP, el archivo deberá comenzar por 0x504B:

14.5) CAFEBABE el número mágico de ByteCode

Para identificar los programas en bytecode, es decir, utilizado por Java como identificador para archivos de clases compilados. Los 32 primeros bits del programa serán siempre: CA FE BA BE.

Y su significado si lo transformamos a decimal sería: (CAFEBABE)^16 = (3.405.691.582)^10

Muestra de ello, es que si nos metemos en la calculadora de Windows y escribimos CAFE BABE, podemos ver su equivalente en binario, decimal y octal:

14.6) Como saber sobre que versión de JDK está compilado un archivo .class mediante a minor versión y major versión bytecode Java

Si compilamos un fichero (.java) a bytecode (.class), para poder leer el fichero, necesitamos ejecutarlo sobre la misma versión de JDK que fue compilado.

Además de los magic numbers, en nuestro fichero de bytecode pasado a hexadecimal también tenemos la minor versión y la major versión.

En este caso, estamos usando una versión mayor, concretamente la versión 3C (en hexadecimal) que sería equivalente a 60 (en decimal). Podemos confirmarlo, ejecutando el comando:

javap -verbose NombreClase.class | findstr “major” (para Windows)

javap -verbose NombreClase.class | grep “major” (para Linux)

En nuestro fichero de ejemplo sería:

Os adjunto un listado con algunas de las versiones de JDK:

  • Java 1.1 uses major version 45
  • Java 1.2 uses major version 46
  • Java 1.3 uses major version 47
  • Java 1.4 uses major version 48
  • Java 5 uses major version 49
  • Java 6 uses major version 50
  • Java 7 uses major version 51
  • Java 8 uses major version 52
  • Java 9 uses major version 53
  • Java 10 uses major version 54
  • Java 11 uses major version 55
  • Java 12 uses major version 56
  • Java 13 uses major version 57
  • Java 14 uses major version 58
  • Java 15 uses major version 59
  • Java 16 uses major version 60

14.7) Gosling nos explica la anécdota que originó la famosa los números mágicos CAFEBABE

El nombre proviene de un lugar donde Gosling y compañía (los desarrolladores del lenguaje), solían tomar café conocido como St Michael’s Alley. Al cerrarse la cafetería, se convirtió en un santuario budista. Al que bautizaron como CAFEDEAD. Y un día, medio bromeando, comprobaron que estaba en formato hexadecimal. Y tras una inspiración repentina James Gosling, convirtió CAFEBABE en el formato de archivo de una clase y CAFEDEAD en el formato de objeto persistente. Al final, el formato persistente de un objeto (CAFE DEAD) se sustituyó por RMI, pero aún podemos ver el mítico CAFE BABE en nuestro código.

Aunque por lo visto, la intención inicial era hacer una metáfora con JAVA CAFE, pero dado que no hay ni J ni V en hexadecimal, se escribió CAFE BABE.

Lo confirma James Gosling en el siguiente comentario:

Solíamos ir a almorzar a un lugar llamado St Michael’s Alley. Según la leyenda local, en el pasado profundo y oscuro, los Grateful Dead solían actuar allí antes de triunfar. Era un lugar bastante original que definitivamente era un lugar de Grateful Dead Kinda. Cuando Jerry murió, incluso levantaron un pequeño santuario de quesos budistas. Cuando íbamos allí, nos referíamos al lugar como Café Dead. En algún momento a lo largo de la línea, se notó que se trataba de un número HEX. Estaba renovando un código de formato de archivo y necesitaba un par de números mágicos : uno para el archivo de objeto persistente y otro para las clases. Usé CAFEDEAD para el formato de archivo de objeto y en greppingpara palabras hexadecimales de 4 caracteres que encajan después de “CAFE” (parecía ser un buen tema), le di a BABE y decidí usarlo. En ese momento, no parecía terriblemente importante o destinado a ir a ningún lado más que a la basura de la historia. Entonces CAFEBABE se convirtió en el formato de archivo de clase y CAFEDEAD fue el formato de objeto persistente. Pero la función de objetos persistentes desapareció y, junto con ella, desapareció el uso de CAFEDEAD; finalmente fue reemplazada por RMI ”- James Gosling

15. Trabajando con un IDE

15.1) ¿Qué es un Integrated Development Enviroment (IDE)?

A diferencia de un editor de texto (Bloc de notas) como el que hemos utilizado anteriormente un Entorno de Desarrollo Integrado (IDE) nos ofrece un conjunto de herramientas para desarrollar nuestro código mucho más rápido. Algunas de las herramientas y ventajas que nos ofrece un IDE son:

  • Editor de código: nos facilita un editor de texto donde podremos picar nuestro código directamente.
  • Detección automática de algunos errores: el IDE intentará ayudarnos a detectar errores en muchas situaciones, más abajo veremos un ejemplo de ello.
  • Depurador: el depurador o debugger (en inglés), que nos permitirá detener el flujo de nuestro programa en una determinada instrucción permitiendo avanzar más detenidamente y así localizar y solucionar errores de una manera mucho más rápida y fácil. A la acción de depurar errores se conoce usualmente como debuggear.
  • Compilador: No realiza la compilación de nuestro programas con tan solo pulsar un botón evitando así el tener que utilizar los comandos javac [nombredelarchivo.class] y después ejecutarlo mediante el comando java [nombredelarchivo]. Como hicimos en clases anteriores, sino que el mismo IDE se encarga automáticamente.
  • Consola/Terminal: nos permite mostrar una consola dentro del propio IDE en la que ejecutará nuestros programas en el caso de que dichos programas sean programas de consola. Sin tener que abrir el cmd y ejecutarlos desde allí.
  • Menos tiempo y menos esfuerzo: el IDE nos intentará ayudar en muchos momentos del desarrollo mostrando sugerencias mediante el asistente Intelligence.

15.2) Tipos de IDE ¿Qué IDE instalo para trabajar con Java?

Existen multitud de IDE’s:

Cualquiera de ellos tiene sus ventajas y sus desventajas. Nosotros vamos a utilizar Eclipse debido a que se utiliza en muchas compañías y es totalmente gratuito.

15.3) Instalando Eclipse

Para descargar Eclipse, tenéis que visitar su página web y en este caso vamos a instalar la versión más completa de Eclipse la versión Java EE de Eclipse. Para ello, una vez tengamos el fichero descargado, seleccionamos:

En este caso, vemos que automáticamente nos detecta automáticamente dónde tenemos la versión de JDK y nos asigna dicha ruta en la instalación:

Y finalmente vemos que se inicializa la instalación:

Y finalmente, solo tenemos que ejecutar el icono que se nos a creado en el escritorio:

El cual abrirá nuestro entorno de desarrollo con el que desarrollaremos nuestros programas en Java:

15.3) Realizando la creación de un proyecto de Java con Eclipse

Para crear un proyecto en Eclipse vamos a File>New>Project…

Y seleccionamos Java>Java Project:

Y escribimos el nombre del proyecto en nuestro caso HelloWorld:

15.4) Modificando la versión del JDK sobre la que se ejecutará nuestro proyecto en Eclipse

Anteriormente, durante la compilación manual, hemos aprendido cómocambiar la versión de JDK de la que tenemos actualmente a otra versión.

Ahora vamos a aprender a realizar dicha modificación en Eclipse. Cuando creamos un proyecto, además podemos seleccionar los diferentes JDKs sobre los que trabajar. Para ello, podemos seleccionar Use default JRE

Y si nos fijamos podemos ver los diferentes JSKs que tenemos configurados en nuestro entorno. En este caso, solamente tenemos el JDK que nos ha detectado cuando hemos realizado la instalación. Vamos a añadir la versión 8 de JDK, para ello pulsamos sobre Add…

Y seleccionamos Standard VM y pulsamos sobre Directory y seleccionamos la versión de JDK:

Y vemos que nos reconoce la versión solo nos falta pulsar Finish:

Y vemos que tras la finalización la ventana de creación de un proyecto nos está indicando que no podemos usar el compilador en la versión 16 con el JDK 1.8 (la versión 8 de JDK). Por tanto tenemos que cambiar la versión de compilación a la versión 1.8. Para ello, vamos a:

Y modificamos la versión del compilador de la 16:

Por la correspondiente a la versión de JDK que vamos a utilizar, en nuestro caso, a la versión 1.8:

Ahora, por ejemplo, podríamos trabajar con la versión 1.8 de JDK en Eclipse y tener configuradas las variables de entorno del sistema con la versión 16 de JDK:

Pese a ello, nosotros vamos a utilizar la versión 16 de JDK en la creación de nuestro Hola Mundo:

Y finalmente, pulsamos sobre finalizar:

Y podemos ver que ya hemos creado nuestro proyecto:

En el caso que no se nos vea el Package Explorer, tendremos que ir a Windows>Show View>Package Explorer

15.5) Creando la clase principal (Main) desde Eclipse

Una vez creado el proyecto, vamos a crear una clase llamada HelloWorld, para ello vamos a:

Y en la creación de dicha clase, podemos indicar que será una clase Main marcando la pestaña public static void main (String[] args) evitándonos así el tener que escribirlo como habíamos hecho anteriormente en la creación manual:

15.6) Explicando que son los packages de Java

Un paquete (algo similar a una carpeta) agrupa un conjunto de clases en Java se nos ha creado una clase llamada HelloWorld, con extensión .java:

De hecho, si vemos la estructura de carpetas del proyecto en Windows pulsando sobre Show In > System Explorer:

Podemos ver que al final un package (paquete) en Java, no deja de ser un directorio que agrupa a elementos de Java (como clases, interfaces, etc.). Vamos a verlo:

15.7) Presentando a Intelligence el auxiliar de código de Eclipse

Y finalmente, solamente tenemos que escribir la famosa ya para nosotros instrucción System.out.println(“Hello World”);

Si nos fijamos, conforme vamos escribiendo nuestras clases, en Eclipse, concretamente cuando escribimos el . nos aparece un asistente llamado Intelligence que tiene la finalidad de que el escribir código en nuestro IDE sea mucho más sencillo.

Existe la posibilidad de abrir el asistente en cualquier momento pulsando la tecla CONTROL junto a la tecla ESPACIO.

Finalmente, una vez escribamos nuestro programa al completo podemos ejecutarlo simplemente pulsando sobre el botón de play:

O bien pulsando sobre la clase principal (Main), en este caso HelloWorld.java, Run As > Java Application:

En ambos casos, el resultado será el siguiente:

15.8) Bombillas y errores: Bulbs Warnings (bombillas de advertencia), Bulbs Errors (bombillas de errores) y Errors (errores)

Eclipse nos proporciona una serie de ayudas realizadas por el IDE para realizar una especie de advertencias visuales que son conocidas como Bulbs Warnings. Por ejemplo si escribimos mal la instrucción System.out.println(), sustituyendo la S en mayúsculas por una en minúsculas, Eclipse nos muestra un error. Recordad que Java es Key Sensitive, y que por tanto distingue mayúsculas y minúsculas y nos aparecerá por tanto el mismo error que anteriormente habíamos realizado en la compilación manual. Podemos ver que nos aparece una especie de bombillita que nos intentará ofrecer ciertas soluciones:

Si ejecutamos el código sin reparar el error, además nos indicará que es en la línea 7 donde aparece el error:

Para repararlo, también podemos pulsar sobre la bombillita y coger la solución o al menos tener una pequeña pista sobre cuál es el motivo por el que nuestro programa no realiza la compilación correctamente.

Dentro de los errores de las bulbs warnings tenemos varios tipos. Vamos a verlos:

  • Bombillas informativas (Bulbs Warnings): nos informan de cosas que no tienen mucho sentido como declarar una variable y posteriormente no usarla.

Si nos situamos sobre la bulb (bombillita) podemos ver que nos informa de que la variable greeting no es usada:

De hecho si desplegamos la ventana de Problems visitando Windows>Show View>Problems:

Podemos ver que dicha advertencia se trata de un Warning, por lo que no impedirá la ejecución del programa:

Si lo ejecutamos vemos que funciona correctamente:

Si pulsamos encima de la bulb, podemos ver que una de las soluciones que nos ofrece es eliminar dicha variable:

Lo que nos permitiría eliminar dicha advertencia:

  • Bombillas de errores (Bulbs Errors): aunque ya nos hemos encontrado y resuelto este problema, podemos ver que es un error que no permite la ejecución del programa:
  • Errores directos (Errors), sin advertencias: se producen cuando una instrucción tiene errores y el IDE no es capaz de ofrecernos sugerencias. Por ejemplo:

16. Cierre del artículo

16.1) Conclusión final

Espero que os haya sido de utilidad, y espero que os haya servido para aprender alguna cosita. Para acabar, me gustaría agradeceros el que hayáis finalizado la lectura ya os avisaba en al inicio del artículo, el artículo es mega grande ¡Un saludo javer@s! 👋😊

--

--

David Bernal González

Me apasiona el investigar sobre lenguajes como: Java, Spring Boot, C#, JavaScript, Flutter, Angular, SQL...