Compilando mediante la variable CLASSPATH en el bash de Linux

Posted: 14/02/2013 in Java
Tags: , , , ,

Con la intención de avanzar en mi aprendizaje de Java, me descargué un pequeño proyecto al que poder modificar el código e ir así observando los resultados.
Encontré un programa llamado GridWorld, que además de estar expresamente destinado para este mismo fin, está muy bien documentado.

Este programa se descarga en forma de .zip. Una vez descomprimido, el directorio raíz se organiza de la siguiente manera:

$ ls -l
total 120
-rw-r--r-- 1 dani dani 68 Apr 16 2007 build.properties
-rw-r--r-- 1 dani dani 3323 Apr 16 2007 build.xml
drwxr-xr-x 3 dani dani 4096 Apr 16 2007 framework
-rw-r--r-- 1 dani dani 100063 Apr 16 2007 gridworld.jar
drwxr-xr-x 4 dani dani 4096 Apr 16 2007 javadoc
drwxr-xr-x 5 dani dani 4096 Apr 16 2007 projects

Quiero compilar el archivo ./projects/firstproject/BugRunner.java, que contiene el siguiente código:

import info.gridworld.actor.ActorWorld;
import info.gridworld.actor.Bug;
import info.gridworld.actor.Rock;

public class BugRunner
{
    public static void main(String[] args)
    {
        ActorWorld world = new ActorWorld();
        world.add(new Bug());
        world.add(new Rock());
        world.show();
    }  
}

La clave que me permitirá entender el error que obtendré cuando intente compilar esto directamente se encuentra en las tres primeras líneas, donde se están importando las clases:

im1

El compilador no encuentra las clases. Esto se debe a que, a diferencia de los de otros lenguajes, como el de C, al compilador de Java hay que especificarle dónde están las librerías (en su caso, las clases) que ha de utilizar. Para este menester tenemos la variable de entorno CLASSPATH, cuyo valor (que es la ruta de nuestras clases) es utilizado por la máquina virtual de Java para encontrar las clases definidas por nosotros. Básicamente hay dos maneras de utilizar esta variable en la línea de comandos: la primera, utilizándola como una opción de javac (el compilador que utilizamos), es decir:

$ javac -classpath la_ruta_de_nuestras_clases archivo.java

Los detalles están explicados en este enlace.

Y la segunda manera, que es la que he utilizado yo por parecerme la más natural: tratando CLASSPATH como una variable de entorno más del bash:

$ export CLASSPATH="ruta_a_seguir_1:ruta_2"

Podemos definir tantas rutas como queramos separando cada una de ellas por dos puntos. Es importante especificar “export” porque así hacemos que el valor de esta variable pueda ser utilizada en cada subproceso que invoquemos; de no exportarla, el valor de CLASSPATH estaría solo restringido a la shell, lo cual no nos interesa.
Una vez especificado el valor de CLASSPATH, que es un conjunto de rutas, el compilador empezará a buscar las clases, siguiendo el orden de cada ruta que le hemos indicado, cada vez que en el código fuente del archivo que compilemos hagamos una invocación a cada una de ellas.

En el caso que nos atañe tengo, como decía más arriba, el archivo BugRunner.java, que depende de una serie de clases. Las clases que he de buscar están en la carpeta raíz, GridWorldCode/, en el paquete de clases GridWorldCode/gridworld.jar, y, por supuesto, en el directorio donde se encuentra el mismo BugRunner.java, es decir, en GridWorldCode/project/firstProject/, ya que aquí se creará BugRunner.class.

Voy a indicárselo a CLASSPATH utilizando rutas relativas. A continuación compilaré mediante javac (por supuesto, sin utilizar la opción -classpath, pues las rutas que necesitamos ya están establecidas), y finalmente ejecutaré el programa:

im2

Y ya lo tenemos.

Puede pasar que al ejecutar un programa después de haber definido CLASSPATH y compilarlo (exitosamente) mediante javac obtengamos un

Exception in thread "main" java.lang.NoClassDefFoundError

Eso es porque, aunque el programa ha compilado, ha habido un error durante la ejecución: en particular, no se ha encontrado la clase que saldrá especificada a continuación de este error. En principio eso es debido a que la clase (o las clases) que falta no está en ninguna ruta de las introducidas en nuestra variable de entorno, por lo que habrá que revisar qué rutas faltan por definir, o incluso qué rutas están mal definidas, en CLASSPATH.

Vale decir que muchos entornos de desarrollo, como por ejemplo Eclipse, ofrecen un soporte gráfico en el que poder definir las variables de entorno.

Comments
  1. […] de cambiar su dirección) se llama BugRunner.java. El código en su forma original está copiado en el primer post del blog. Lo único que hacía ese código era crear un tablero, crear un bicho, una roca (que no hace nada, […]

Leave a comment