[jboss-user] [Management, JMX/JBoss] - Re: Interacting with the LoaderRepository MBean

miclopezalv do-not-reply at jboss.com
Mon Sep 25 14:54:44 EDT 2006


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=3973978#3973978

Reply to the post : http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&p=3973978



More information about the jboss-user mailing list