UP | HOME

Java: construir proyectos

Table of Contents

Llegados a este punto ya sabes cómo compilar programas en Java compuestos por un único archivo fuente. En este apartado te vas a enfrentar a escenarios un poco más complicados, y realistas, donde tenemos programas escritos en Java organizados en proyectos compuestos por varios directorios y archivos fuentes.

Introducción y referencia

Antes de comenzar a desarrollar programas en Java recuerda que es fundamental instalar el JDK (Java Development Kit). Una vez hayas completado la instalación, tendrás acceso a un compilador llamado javac y a una máquina virtual que puedes ejecutar con el comando java. Además, dispondrás de otras herramientas útiles como un empaquetador jar o un generador de documentación como javadoc.

Puedes acceder a toda la documentación al respecto desde la web dev.java.

Compilar y ejecutar, todo en la misma carpeta

Imagina que tienes un programa que consta de tres fuentes en la raíz del proyecto:

  • Main.java que contiene la clase principal (entrada al programa)
  • Tarea.java
  • GestorTareas.java

Para compilar, desde la carpeta raíz del proyecto:

$ javac *.java

Y, para ejecutar, desde la raíz del proyecto:

$ java Main

Compilar y construir en otra carpeta

Ahora, veamos cómo reestructurar el proyecto organizándolo en una jerarquía como ves:

project/
|-- src/
|    |-- Tarea.java
|    |-- GestorTareas.java
|    |-- Main.java
|-- build/
|-- README.md

Compilamos/construímos desde la raíz del proyecto para dejar los resultados *.class en la carpeta build:

$ javac -d build src/*.java

Ahora podemos ejecutar el programa con la opción -cp (classpath):

$ java -cp build Main

Uso de paquetes

Cuando un programa crece en cantidad de fuentes y complejidad tenemos que organizar nuestro proyecto Java en paquetes. En clase, hemos visto qué son los paquetes en Java y qué problema resuelven.

Lo primero que tenemos que hacer es reestructurar la jerarquía de directorios para adaptarla a la jerarquía estándar cuando se usan paquetes.

Se sigue una convención de nomenclatura y una estructura de directorios que es estándar y ampliamente aceptada. Esta estructura ayuda a organizar el código de manera lógica y a evitar conflictos de nombres.

Detalles de la estructura:

  • Raíz de proyecto: src/main/java (esta es la estructura de Maven o Gradle, y la que vamos a usar nosotros)
  • Prefijo único de paquete: se usa un dominio al revés. Por ejemplo, si una empresa/organización tiene como dominio miorganizacion.com, el prefijo del paquete es com.miorganizacion
  • Paquetes: cada parte del nombre del paquete se convierte en subdirectorios y se pueden añadir, a partir del prefijo anterior, todos los subdirectorios que se necesiten y se consideren oportunos

Por ejemplo, si partimos de mi dominio proferoman.com, el proyecto anterior lo podríamos organizar así:

project/
├── build
├── README.md
└── src
    └── main
        └── java
            └── com
                └── proferoman
                    ├── hw1
                    │   └── HelloWorld.java
                    ├── hw2
                    │   └── HelloWorld.java
                    └── Main.java

Y, ahora, cada fichero tiene que empezar con la instruccion package seguida del nombre del paquete al que forma parte ese fichero. Al compilar veremos que hay un error porque, ahora, es necesario importar la clase que queremos usar.

Tras importar, entonces sí, ahora ya podemos compilar sin problema:

$ javac -d build src/main/java/com/proferoman/Main.java src/main/java/com/proferoman/hw1/HelloWorld.java src/main/java/com/proferoman/hw2/HelloWorld.java

Y vemos como, pen build/, se mantiene la estructura de paquetes:

build/
└── com
    └── proferoman
        ├── hw1
        │   └── HelloWorld.class
        ├── hw2
        │   └── HelloWorld.class
        └── Main.class

Y, otro cambio más, a la hora de ejecutar tenemos que indicar la clase principal especificando su paquete completo:

$ java -cp build com.proferoman.Main

Empaquetar programas Java: Java ARchive (JAR)

En Java, es común agrupar varios archivos .class en un solo archivo para facilitar su manejo y distribución. Por esta razón, se utilizan los archivos JAR (Java ARchive files). Este formato permite empaquetar nuestros programas Java de manera sencilla, facilitando su distribución y ejecución al concentrar todos los componentes necesarios en un único archivo .jar.

Para profudizar en este apartado, de nuevo, te tengo que remitir a la documentación que puedes encontrar en [dev.java](https://dev.java/learn/).

Aquí te muestro un resumen de lo que veremos en clase con mayor profundidad.

Contenido de los ficheros JAR

En los ficheros JAR se incluyen:

  • Todos los .class
  • Un archivo de manifiesto (opcional) con información sobre el contenido del fichero JAR (metadatos)
  • Archivos de recurso como: configuraciones, imágnenes, logotipos, iconos, cadenas de traducción…
  • Cualquier otro archivo necesario para la aplicación

Sobre el archivo de manifiesto

El archivo de manifiesto es un archivo que tendrás que crear con el nombre MANIFEST.MF. En este archivo:

  • Se especifican metadatos.
  • Estos metadatos se especifican con pares "clave-valor".
  • Si se pretende que el archivo JAR sea ejecutable hay que especificar la clase principal

Por ejemplo, imagina que partidmos de un proyecto como este:

project_jar/
├── build
├── README.md
└── src
    └── main
        └── java
            └── com
                └── proferoman
                    ├── hw1
                    │   └── HelloWorld.java
                    ├── hw2
                    │   └── HelloWorld.java
                    └── Main.java

Vamos a incluir el archivo "manifest". Creálo en src/main/resources/META-INFO/MANIFEST.MF y añade lo siguiente en él (hay que dejar una línea en blanco al final del archivo):

Manifest-Version: 1.0
Created-By: Román Martínez
Main-Class: com.proferoman.Main

Ahora, ya puedes construir el programa:

$ javac -d build src/main/java/com/proferoman/*.java src/main/java/com/proferoman/hw1/*.java src/main/java/com/proferoman/hw2/*.java

Empaquetarlo en un jar:

# Crea el JAR con los archivos .class compilados
$ jar -cvfm build/miprograma.jar src/main/resources/META-INF/MANIFEST.MF -C build .

Significado de las opciones -cvfm:

  • c o --create se emplea para indicar a jar que tiene que crear el fichero
  • v o --verbose se emplea para que nos informe con detalle de lo qué pase
  • f o --file se emplea para indicar el nombre del fichero JAR resultante
  • m o --manifest se emplea para indicar el fichero con el manifest

Por último, para ejecutar un programa empaquetado con en un jar:

$ java -jar build/miprograma.jar

Creación de bibliotecas

En clase ya hemos hablado del concepto de biblioteca de software (library).

Aquí te muestro un resumen de lo visto en clase. Partamos de este proyecto, preparado para construir una biblioteca en JAR:

my_library
└── src
    └── main
        ├── java
        │   └── com
        │       └── example
        │           └── dateformatter
        │               └── DateFormatterUtil.java
        └── resources
            └── META-INF
                └── MANIFEST.MF

Los pasos que hay que llevar a cabo son estos:

  1. Compilar: javac -d build src/main/java/com/example/dateformatter/DateFormatterUtil.java
  2. Empaquetar: jar -cvfm build/dateformatter-lib.jar src/main/resources/META-INF/MANIFEST.MF -C build .

Ahora, para usar la librería en otro proyecto (al que he llamado project):

  1. Creamos un proyecto con una estructura típica de paquetes en la que tenemos un nuevo directorio dentro de src/main llamado libs como ves aquí (donde metemos las librerías empaquetadas en .jar):
project
└── src
    └── main
        ├── java
        │   └── es
        │       └── eed
        │           └── App.java
        ├── libs
        │   └── dateformatter-lib.jar
        └── resources
            └── META-INF
                └── MANIFEST.MF
  1. Ahora, costruimos el proyecto con la biblioteca incluida (la novedad es que usamos la opción -cp para indicar donde están las bibliotecas a incluir): javac -cp src/main/libs/dateformatter-lib.jar -d build src/main/java/es/eed/App.java
  2. Y ejecutamos inluyendo las bibliotecas y todos los classpath separados por el carácter dos puntos (:): java -cp build:src/main/libs/dateformatter-lib.jar es.eed.App

    En Windows hay que usar como separador el punto y coma (;) y hay que poner el classpath entre comillas: java -cp "build;src/main/libs/dateformatter-lib.jar" es.eed.App

  3. Crear un fat-jar con todas las dependencias dentro (a modo de información): habría que desempaquetar todas las bibliotecas para añadirlo todo al JAR final junto al proyecto. Resumen de pasos:
    • Compilar el proyecto
    • Crear el MANIFEST.MF con Main-Class: es.eed.APP para poder ejecutarlo (JAR ejecutable)
    • Extraer el contenido de la biblioteca a una carpeta temporal (jar -xf src/main/libs/...jar)
    • Empaquetar todo en un solo JAR: jar -cf programa.jar -C build/ . -C temp_lib/ .
    • Ejecutar: java -jar programa.jar

En Maven se puede usar el plugin Maven Shade para hacerlo y en Gradle Shadow.

Author: Román Ginés Martínez Ferrández

Created: 2026-02-17 mar 16:19

Validate