Por ejemplo, si las clases, las librerías, o las entradas de registro de Window de instalaciones anteriores permanecen en nuenstro sistema después de una actualización, hay una oportunidad de que la mezcla del nuevl software sea la causante de nuestros problemas y necesita ser investigada y eliminada. Las oportunidades para los problemas relacionados con la mezcla de versiones de software se ha incrementado con el uso de diferentes versiones de herramientas para desarrollar software de la plataforma Java.
La sección sobre Problemas con Versiones al final de este capítulo proporciona una lista completa de las principales versiones de la plataforma Java para ayudarnos a resolver nuestros problemas con versiones de software.
Para examinar el CLASSPATH, tecleamos esto en la línea de comando:
Windows 95/98/NT:
echo %CLASSPATH%
Unix:
echo $CLASSPATH
Las clases Java se cargan en primer lugar, primera forma básica de la lista CLASSPATH. Si la variable CLASSPATH contiene una referencia a un fichero lib/classes.zip, que apunta a una instalación diferente de la plataforma Java, esto peude causar que se cargen clases incomplatibles.
Nota: En la plataforma Java 2, las clases del sistema se eligen antes de cualquier clases de la lista CLASSPATH para minimizar de que se caeguen clases Java anteriores a la clase Java 2 del mismo nombre.
La variable CLASSPATH puede obtener su configuración desde la línea de comandos o desde las selecciones de configuración como aquellas especificadas en el Entorno de Usuario sobre Windows NT, un fichero autoexec.bat, o un fichero de arranque del shell .cshrc sobre Unix.
Podemos controlar las clases de la Máquina Virtual Java usadas para compilar nuestros programas con una opción especial de la línea de comandos que nos permite suministrar el CLASSPATH que querramos. La opción y parámetro de la plataforma Java 2 -Xbootclasspath classpath, y las versiones anteriores usan -classpath classpath y -sysclasspath classpath. Sin importar la versión que estamos ejecutando, el parámetro classpath especifica el classpath del sistema y del usuario, y los ficheros zip o JAR a usar en la compilación.
Para compilar y ejecutar el programa Myapp.java con un CLASSPATH suministrado en la línea de comandos, usamos las siguientes instrucciones:
Windows 95/98/NT:
En este ejemplo, la plataforma Java está instalada en el directorio C:\java. Tecleamos los siguiente en una sóla línea:
javac -J-Xbootclasspath:c\java\lib\tools.jar;c: \java\jre\lib\rt.jar;c:\java\jre\lib\i18n.jar;. Myapp.java
No necesitamos la bandera -J para ejecutar el programa Myapp compilado, sólo tecleamos esto en una sóla línea:
java -Xbootclasspath:c:\java\jre\lib\rt.jar;c: \java\jre\lib\i18n.jar;. Myapp
Sistemas Unix:
En este ejemplo, la plataforma Java está instalada en el directorio /usr/local/java. Tecleamos todo en una sóla línea:
javac -J-Xbootclasspath:/usr/local/java/lib/tools.jar: /usr/local/java/jre/lib/rt.jar: /usr/local/java/jre/lib/i18n.jar:. Myapp.java
No necesitamos la bandera -J para ejecutar el programa Myapp compilado, sólo tecleamos esto en un sóla línea:
java -Xbootclasspath:/usr/local/java/jre/lib/rt.jar: /usr/local/java/jre/lib/i18n.jar:. Myapp
Por ejemplo, una aplicación podría estar usando la clase Password que escribimos para ella o podría estar cargando la clase Password desde la herramienta IDE instalado.
Deberíasmos ver cada nombre de fichero zip o Jar como se vé aquí:
$ java -verbose SalesReport
[Opened /usr/local/java/jdk1.2/solaris/jre/lib/rt.jar
in 498 ms]
[Opened /usr/local/java/jdk1.2/solaris/jre/lib/i18n.jar
in 60 ms]
[Loaded java.lang.NoClassDefFoundError from
/usr/local/java/jdk1.2/solaris/jre/lib/rt.jar]
[Loaded java.lang.Class from
/usr/local/java/jdk1.2/solaris/jre/lib/rt.jar]
[Loaded java.lang.Object from
/usr/local/java/jdk1.2/solaris/jre/lib/rt.jar]
Otra ventaja es que algunas veces los problemas de software pueden ser atribuidos a condiciones de carrera donde el mismo segmento de código se convierte en impredecible debido al tiempo entre cada iteracción del programa. Si controlamos el código de operación desde la línea de comandos en lugar de añadir sentencias de depuración println, podemos arreglar la secuencia de problemas que causa las condiciones de carrera que vienen desde el código println. Esta técnica también nos evita tener que añadir y eliminar las sentencias println y tener que recompilar nuestro código.
Esta técnica requiere que usemos una propiedad del sistema como bandera de depurado y que incluyamos código en la aplicación para comprobar que el valor de esta propiedad del sistema. Para activar la información de depuración desde la línea de comandos en el momento de la ejecución, arrancamos la aplicación y seleccionamos la propiedad del sistema debug a true de esta forma:
java -Ddebug=true TestRuntime
El código fuente que necesita la clase TestRuntime para examinar esta propiedad y configurar la bandera booleana debug de es el siguiente:
public class TestRuntime {
boolean debugmode; //global flag that we test
public TestRuntime () {
String dprop=System.getProperty("debug");
if ((dprop !=null) && (dprop.equals("yes"))){
debugmode=true;
}
if (debugmode) {
System.err.println("debug mode!");
}
}
}
Una forma de eliminar las sentencias de depuración System.out.println de nuestro código es usar la siguiente optimización del compilador para eleminar los corchetes pre-determinados de nuestos código en el momento de la compilazión y activar alguna algo similar a un depurador pre-procesador.
Este ejemplo usa una bandera booleana estática dmode que cuando se selecciona a false resulta en la eliminación el código de depuración y de las sentencias de depuración. Cuando el valor de dmode se selecciona a true, el código es incluido en el fichero class compilado y está disponible en la aplicación para propósitos de depuración.
class Debug {
//set dmode to false to compile out debug code
public static final boolean dmode=true;
}
public class TestCompiletime {
if (Debug.dmode) { // These
System.err.println("Debug message"); // are
} // removed
}
Para permitie seguir las llamadas, tenemos que arrancan la JVM con los comandos del intérprete java_g o java -Xdebug.
Para listar cada método cuando es invocado durante la ejecución, añadimos la siguiente línea antes del código donde queremos empezar a seguir la pista y añadimos la correspondiente línea traceMethodCalls con el argumento seleccionado a false para desactivar el seguimiento. La información de seguimiento se muestra en la salida estándard.
Para ver cada línea en bytecodes cuando se ejecutan, añadimos la siguiente línea al código de nuestra aplicación:// set boolean argument to false to disable Runtime.getRuntime().traceMethodCalls(true); callMyCode(); Runtime.getRuntime().traceMethodCalls(false);
También podemos añadir la siguiente línea para que nuestra aplicación vuelque la pila usando el método dumpStack de la clase Thread. La salida de este volcado de pila se explica en Análisis y Seguimiento de la Pila, pero ahora podemos pensar en la pila como un apunte de los threads que se están ejecutando en la JVM.// set boolean argument to false to disable Runtime.getRuntime().traceInstructions(true); callMyCode(); Runtime.getRuntime().traceInstructions(false);
Thread.currentThread().dumpStack();
Para obtener acceso a la información de variables lcoales, tenemos que obtener el fuente (src.zip o src.jar) y recompilarlo con una bandera debug. Podemos obtener el fuente de la mayoría de las clases java.* classes con la descarga de los binarios desde java.sun.com.main[1] locals No local variables: try compiling with -g
Una vez hayamos descargado el fichero src.zip o src.jar, extraemos sólo los ficheros que necesitamos. Por ejemplo, para extraer la clase String, tecleamos esto en la línea de comandos:
ounzip /tmp/src.zip src/java/lang/String.java
Recompilamos la clase o clases extraidas con la opción -g. También podemos añadir nuestros propios diagnósticos adicionales sobre el fichero fuente en este momento.jar -xf /tmp/src.jar src/java/lang/String.java
javac -g src/java/lang/String.java
El compilador Java 2 javac ofrece más opciones que sólo la opción original -g para código de depuración, y podemos reducir el tamaño de nuestras clases usando -g:none, que nos ofrece una reducción de un 10% del tamaño.
Para ejecutar la aplicación con las nuevas clases compiladas, necesitamos usar la opcioón bootclasspath para que esas clases se utilicen en primer lugar.
Tecleamos lo siguiente en una sóla línea con espacio antes de myapp.
Plataforma Java 2 Win95/NT:
Este ejemplo asume que la plataforma Java está instalada en c:\java, y los ficheros fuente están en c:\java\src:
jdb -Xbootclasspath:c:\java\src;c:\java\jre\lib\rt.jar;c: \java\jre\i18n.jar;. myapp
Sistemas Unix:
Este ejemplo asume que la plataforma Java está instalada en /usr/local/java, y los ficheros fuente están en /usr/local/java/src.
jdb -Xbootclasspath:/usr/java/src; /usr/java/jre/lib/rt.jar; /usr/java/jre/i18n.jar;. myapp
La siguiente vez que ejecutemos el comando locals veremos los campos internos de la clase que deseamos analizar.