Recargar una clase modificada.

dmolano
03 de Septiembre del 2005
SO: Windows XP
JVM: 1.4.2_02<br>
PROBLEMA: al recargar una clase, que ha sido modificada después de la primera carga, la JVM sigue manteniendo la versión que cargó inicialmente.<br>
OPERATORIA: he creado dos clases:<b>Lanzador.java</b> y <b>Mutante</b>.java<br>
<b>Lanzador.java</b> crea un objeto <i>URLClassLoader</i>, carga la clase <b>Mutante.java</b> a través de este cargador.<br>
<b>Mutante.java</b> devuelve la versión.<br>
<b>Lanzador.java</b>, entre carga y carga de la clase <b>Mutante.java</b>, espera a que se pulse una tecla. De esta forma, puedo recompilar la clase <b>Mutante.java</b> con otro número de versión, y sustituir en <i>"c:\PRUEBAS\ADC\adc"</i> la clase <b>Mutante.java</b> recompilada.<br>
El resultado es siempre el mismo: el cargador de clases, que he creado, no carga la nueva clase modificada.<br>
/*********************Lanzador.java*************************/
package adc;


import java.io.*;
import java.lang.reflect.*;
import java.net.*;

public class Lanzador {
public Lanzador() {
while (true) {
try {
System.out.println("Pulse una tecla.");
System.in.read();
cargarNuevaVersion();
}
catch (IOException ioe) {
ioe.printStackTrace();
}
}
}

private void cargarNuevaVersion() {
URLClassLoader cargador;
Class claseMutante;
Method metodoGetVersion;

try {
URL[] urls = {
new File("c:\PRUEBAS\ADC/").toURL()};

cargador = new URLClassLoader(urls);
System.out.println("Cargador actual:" +
Thread.currentThread().getContextClassLoader().
toString());
claseMutante = Class.forName("adc.Mutante", true,
cargador);
metodoGetVersion = claseMutante.getMethod("getVersion", null);
System.out.println( (String) (metodoGetVersion.invoke(null, null)));
metodoGetVersion = null;
claseMutante = null;
cargador = null;
System.gc();
}
catch (InvocationTargetException ex) {
ex.printStackTrace();
}
catch (IllegalArgumentException ex) {
ex.printStackTrace();
}
catch (IllegalAccessException ex) {
ex.printStackTrace();
}
catch (SecurityException ex) {
ex.printStackTrace();
}
catch (NoSuchMethodException ex) {
ex.printStackTrace();
}
catch (ClassNotFoundException ex) {
ex.printStackTrace();
}
catch (MalformedURLException ex) {
ex.printStackTrace();
}
}

public static void main(String[] args) {
Lanzador lanzador1 = new Lanzador();
}
}

/*********************Mutante.java*************************/

package adc;

public class Mutante {
private static String sVersion = "0.0.0.3";

public static String getVersion() {
return new String(sVersion);
}
}

liukan
03 de Septiembre del 2005
Yo tenía este problema y contacté con dmolano para saber si lo había conseguido resolver. Obtuve respuesta, y me envió la solución y pidiendome que pusiera aquí la respuesta ( cosa que ya tenía pensado hacer). A continuación va la solución que me envió, por cierto la he probado y funciona perfectamente.

****** Contenido del mail ********

El problema se soluciona cuando la clase que hace la carga de las demás está en un directorio y nivel diferente a ellas.

Te pongo un ejemplo.

Clase que carga:

C:AplicacionCargador de VersionesVersCli.class


Resto de las clases de la aplicación, que están en el paquete jdist:


C:AplicacionResto de clasesInicioJdist*.class


La clase que carga las demás "VersCli.class" es la siguiente:



package versjdist;

import java.io.*;
import java.lang.reflect.*;
import java.net.*;

public class VersCli {
static String asArgu = null;
public VersCli() {
while(true){
nuevaVersion();
try{
Thread.sleep(2000L);
}catch(Exception e){}
}
}

private void nuevaVersion(){
URLClassLoader urlcl = null;
Class classAplic = null;
Method metodoAplic = null;
try{
URL urls[] = {new File("C:\Aplicacion\Resto de clases\Inicio/").toURL()};
urlcl = new URLClassLoader(urls);
classAplic = Class.forName("jdist.ConexCli", true, urlcl); //-- Clase inicial
metodoAplic = classAplic.getMethod( "inicio",
new Class[] {Class.forName "java.lang.String")} );
Object obj[] = { asArgu }; //-- Parámetros de la clase
metodoAplic.invoke(null, obj);
obj = null;
}catch( Throwable t){
t.printStackTrace();
}
}

public static void main( String args[] ) {
if(args.length > 0){
asArgu = args[0];
}
VersCli oInicio = new VersCli();
}
}