Ok, i found a work around to this problem, changing the class loader every time
i need add new code to my application.
BackGround:
A class i the JVM is identified by de ClassLoader and the full name of the
class, so everytime you make a new instance, this object is identified by the
class loader that loaded the class and the class name. The problem is when you
have to make several modules of your application to interact generating dynamic
code on the fly.
Whe you create a new ClassLoader object you are just pulling away the od
objects and loading new ones; the old ones are going to be garvage collected
and the new ones are going to be there for your use. This is not really
HotSwapping at all !! because you are just creating a new loader. Any way,
here is the class that do the trick inside JBOSS, using javassist and the
Javassist Loader.
Note: See the delagation of class loaders and the delegation of ClassPools.
public class AdministradorClassPath {
/**
* Ruta de las librerias que deben ser cargadas dinamicamente
*/
//TODO obtener del archivo de propiedades de configuracion de
la aplicacion.
public static final String RUTA_BODEGA =
"../server/default/deploy/bodega.jar/";
//public static final String
protected final Log logger = LogFactory.getLog(getClass());
//Class loader padre de la aplicacion
private ClassPool parentClassPool;
private static AdministradorClassPath instance;
private ClassPool childClassPool;
private ArrayList pathRegister;
private LinkedHashMap<String,Class> clasesCargadas;
private Loader loader;
/**
* instancia Singleton
*/
private AdministradorClassPath(){
setParentClassPool();
setChildClassPool();
//setSwapper();
setLoader();
pathRegister = new ArrayList();
clasesCargadas = new LinkedHashMap<String,Class>();
}
/**
* Inicializa un ClassLoader unico para la instancia del
AdministradorClasspath.
*
*/
public void setLoader(){
if(this.childClassPool!=null){
loader = new
Loader(Thread.currentThread().getContextClassLoader(),this.childClassPool);
loader.delegateLoadingOf("com.its.estructuras.");
logger.info("Cargador de creado correctamente
con el pool: "+this.childClassPool);
}
}
/**
*
* @return instace La instancia singleton de
AdministradorClassPath
*/
public static AdministradorClassPath getInstance() {
if (instance == null) {
instance = new AdministradorClassPath();
}
return instance;
}
/**
* Asigna el pool de cargadores de clase de JBoss, o de
cualuier contenedor
* como el cargador padre, donde debe buscar las clases si
no las encuentra en
* uno de los cargadores hijo.
*
*/
private void setParentClassPool() {
//Crea un nuevo class pool y adiciona el search path
del sistema
//Inicializa y adiciona el classpath del sistema a este
pool de clases.
this.parentClassPool = new ClassPool(true);
}
/**
* Asigna un classPool hijo al ClassPool que representa el pool
de clases
* del sistema. Este pool hijo es el pricipal de la
aplicacion.
*
*/
private void setChildClassPool() {
childClassPool = new ClassPool(this.parentClassPool);
childClassPool.childFirstLookup=true;
}
/**
* Adiciona un nuevo Pool de clases al repositorio
* incluyendo el pool de clases padre del ambiente
* en el servidor de aplicaciones
*
*/
public void adicionarClassPath(String rutaClassPath){
try{
if(!pathRegister.contains(rutaClassPath)){
childClassPool.appendClassPath(rutaClassPath);
pathRegister.add(rutaClassPath);
logger.debug("Se acaba de adicionar un
nuevo class path al administrador: "+rutaClassPath);
}
}catch(NotFoundException e){
e.printStackTrace();
}
}
/**
* Imprime los classpath que contiene el administrador de class
paths.
*
*/
public void printClassPaths(){
for(String path:this.pathRegister){
logger.info(path);
}
}
/**
* Este metodo elimina el pool de clases utilizado y crea uno
* totalmente nuevo.
*
*/
public void limpiarClassPoolYCrearUnoNuevo(){
//Class Pool del sistema
this.setParentClassPool();
//Class Pool utilizado
this.setChildClassPool();
//Crear un nuevo cargador de clases
this.setLoader();
//Limpiar la lista de class paths almacenados
this.pathRegister.clear();
//Limpiar el buffer de clases que han sido cargadas
utilizando el ClassPool del sistema
this.clasesCargadas.clear();
//Forzar recoleccion de las instancias creadas
previamente
System.gc();
logger.info("*******************************************************************");
logger.info("*******************************************************************");
logger.info("********* Se ha limpiado el pool de
clases por completo *********");
logger.info("*******************************************************************");
logger.info("*******************************************************************");
//Adicioanar la ruta de la bodega de almacenamiento,
siempre que se inicializa
//el pool de clases.
this.adicionarClassPath(this.RUTA_BODEGA);
}
/**
* Carga la clase del PoolClases de esta clase. Para ello
obtiene un CtClass que
* luego es pasado a un objeto de tipo Class.
*
* @param fullClassName nombre de la clase completo
* @return class Objeto de tipo Clase requerido
*/
public Class cargarClase(String fullClassName){
Class clazz=null;
try{
if(clasesCargadas.containsKey(fullClassName)){
clazz =
clasesCargadas.get(fullClassName);
}else{
clazz =
loader.loadClass(fullClassName);//this.childClassPool.get(fullClassName).toClass();
this.clasesCargadas.put(fullClassName,clazz);
}
}catch(ClassNotFoundException e){
e.printStackTrace();
}
return clazz;
}
/**
* Saca una CtClass del pool de clases.
* @param fullClassName nombre e la clase completo.
*/
public void sacarClaseDelPool(String fullClassName){
try {
CtClass cTClazz =
this.childClassPool.get(fullClassName);
cTClazz.detach();
//ls clase se deber eliminar del buffer de
clases cargadas
} catch (NotFoundException e) {
System.err.println("No se ha encontrado la
clase solicitada.");
e.printStackTrace();
}
logger.info("*********************************************************************");
logger.info("*La clase: "+fullClassName+" ha sido
sacada del pool de clases. ****");
logger.info("*********************************************************************");
}
/**
* Imprime las clases que se tienen almacenadas en el buffer de
almacenamiento.
*
*/
public void imprimirClasesDelBuffer(){
for(Class c:this.clasesCargadas.values()){
logger.info(c.getName());
}
}
}
View the original post :
http://www.jboss.com/index.html?module=bb&op=viewtopic&p=3973977#3973977
Reply to the post :
http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&p=3973977
_______________________________________________
jboss-user mailing list
[email protected]
https://lists.jboss.org/mailman/listinfo/jboss-user