Archivos del sitio

Programación en Flujo

Posteado por Félix García Borrego en March 21st, 2007

Hace unos meses, gracias al descubrimiento del Best-Seller “FLOW. THE PSYCHOLOGY OF OPTIMAL EXPERIENCE” del autor Mihaly Csikszentmihalyi, he podido redescubrir y bautizar una forma muy especial de enfrentarse a los retos en el trabajo, “Programación en Flujo”.
En primer lugar voy a comentar algunas ideas extraídas del libro.


¿Qué es el Flujo?

Todos hemos sentido en alguna ocasión que teníamos el control total de nuestras acciones. En estas situaciones se siente un gran felicidad a la que podríamos llamamar experiencia óptima; pues bien, el flujo es un estado mental por el cual las personas que lo alcanzan, mientras realizan cierta actividad, se hallan tan involucradas en la actividad que todo lo demas carece de importancia; la experiencia, por sí misma, es tan placentera que las personas la realizan incluso aunque tenga un gran coste, por el puro motivo de hacerla.
Cada persona entra en Flujo por un camino distinto, pero el estado de flujo es fácilmente reconocible, siendo los síntomas mas destacables:
- La tarea que se realiza y la conciencia están unidas: En estado de Flujo nuestra concentración está enfocada a lo que hacemos( unificada y cercana) y no distraída con el mundo exterior.
- Las distracciones no existen: El estado de Flujo es consecuencia de una concentración intensa en el momento presente, y totalmente focalizada en el siguiente objetivo a conseguir.
- La autoconciencia disminuye y se distorsiona el sentido del tiempo: En estado de Flujo la conciencia y la percepción del tiempo se alteran, las horas pueden pasar en lo que parecen ser unos pocos minutos o al contrario.
- La actividad es el fin y no una tarea para alcanzar otros objetivos.
- El estado, se suele alcanzar cuando el desafío es elevado y está equilibrado con las capacidades de la persona.
- La persona debe pensar que puede con el desafío.

En mi época adolescente, espero que no os riais, llamaba a este poco usual estado, “sentirse como un super-guerrero” ante un determinado problema, por ejemplo un examen o un reto personal en el que me sentía seguro y no hace mucho que he descubierto el nombre de ese estado, “entrar en Flujo”.

¿Qué es la programación en Flujo?

Existen muchas técnicas de programación y desarrollo de software, sin pensar mucho, se me vienen a la cabeza ténicas como la programación eXtrema que propone métodos como el desarrollo iterativo, la programación en parejas, la simplicidad del código; o técnicas como el desarrollo guiado por pruebas mas orientadas a la creación de pruebas unitarias para alcanzar los objetivos deseados.
En el fondo todas estas técnicas, aunque están enfocadas en puntos diferentes del mismo problema, intenta mejorar el proceso de desarrollo del software y de forma indirecta mejorar la forma en la que los programadores se enfrentas y manejan el problema.
Una técnica de programación en flujo debería intentar conseguir los mismos objetivos, pero centrándose en la vivencia del programador, declarando que lo importante es la experiencia en si misma y la forma en la que se afronta el problema como mecanismo para alcanzar el objetivo deseado. Que mejor forma de alcanzar la solución a un problema que orientar el desarrollo hacia alcanzar una experiencia óptima en la que cada programador( y meto aquí todas las palabrejas que están presentes en el organigrama informático, jefe de proyectos, Analista funcional, Arquitecto,Dba…) que interviene en el proyecto esté el mayor tiempo posible en estado de Flujo.
Esta técnica podría ser estimulada desde la dirección de la Empresa mediante incentivos sorpresa( y me refiero con esto a recompensas no estipuladas que no se conviertan en objetivos en sí mismas), mediante el reconocimiento profesional, y mediante una equilibrada asignación de tareas; pero sobre todo debe ser absorbida por los desarrolladores para que en caso de tener una predisposición negativa hacia los retos y proyectos, se sientan parte de los mismos, se sumerjan y disfruten por el mero hecho de realizar una tarea, y no la vean como peaje para alcanzar unos objetivos(léase incentivos, nómina, plazos,…).

Esta técnica en realidad no inventa nada nuevo y probablemente se sientan muy reconocidos en ella los llamados frikis de la programación, los gurus,los hackers o los super-coordinadores; y por otro lado es una experiencia que probablemente todo informático haya sentido alguna vez, que sabe reconocer y que estaría deseando volver a alcanzar.

Por mi parte me siento muy afortunado, pero para los informáticos que no hayan sentido nunca esta sensación, mi más sentido pésame.

PD: A los que les haya interesado el tema de la programación en Flujo,espero tener pronto algo un poco más pulido y aplicable al mundo real.
PD: A los que no les haya interesado el tema o les parezca una chorrada, decirles que están en lo cierto, es una ida de pinza, olviden lo escrito, …no le den mas vueltas, no tiene sentido.

Una de inteligencia artificial: buscador de caminos A*

Posteado por Jorge Torres Chacón en March 18th, 2007

Desde mi punto de vista una de las ramas más fascinantes de la programación es la Inteligencia Artificial. Existen 2 definiciones de IA que me gustan especialmente, la primera es muy técnica y la segunda muy práctica, y son las siguientes:

1) Disciplina de la programación dedicada a resolver problemas de complejidad exponencial.
2) Dícese de aquellos actos efectuados por una máquina que de hacerse por humanos se atribuiría a la inteligencia.

Existe una eterna discusión acerca de si las máquinas pueden llegar a ser realmente inteligentes, y en ese sentido recomiendo un libro bastante bueno, “El quinteto de Cambridge” de John L.Casti.

Yo desde luego soy de los que piensa que una máquina sí puede ser inteligente, y llegará un momento en que nos superen. Una de las aplicaciones prácticas que me resulta más interesante (por mi aficción a los juegos) es el buscador de caminos. Son algoritmos por los cuales nuestro objetivo es capaz de sortear los obstáculos y llegar de un punto A a otro B.

El más popular de todos ellos por su eficacia y eficiencia es el buscador A* (o A-estrella, A-Star para los anglosajones). Existe mucha literatura en internet al respecto y recomiendo su lectura si estás interesado en el tema. Groso modo se trata de un mecanismo de selección de trayectoria que utiliza una heurística por la que descarta los nodos de búsqueda de mayor coste y más alejados del destino (en verdad tiene más chicha pero vaya, no tiene sentido extenderse).

Y como no voy a contar algo que ya está en internet os pongo una aplicación práctica de como funciona el A*. Aquí os pongo un pequeño ejecutable hecho en Blitz Basic (para un juego de rol) en el que podeís juguetear con un punto y ponerle obstáculos. Vereís si el condenado es listo o no.

Buscador A*

Funciona tanto en Windows como en Linux usando el wine. Agradecimiento especial a Patrick Lester, cuya ayuda resultó imprescindible.

P.D.: Thank you Patrick, you are on the credits of Caotic Party.

Tree Nation en Agadez, Niger

Posteado por dbejar en March 17th, 2007


El programa medioambiental de las Naciones Unidas United Nations Environment Programme (UNEP) tiene en marcha una campaña para plantar mil millones de arboles Plant for the Planet: Billion Tree Campaign

Uno de los proyectos mas chulos dentro de esa campaña es el proyecto llamado Tree Nation.

Hay fotos reales del proyecto aqui:

Por cierto que yo ya he plantado mi primer arbol virtual, una Acacia Sieberiana. Que apesar de su nombre, se ve que se da bien en Niger, y ademas incrementa la fertilidad del suelo, algo que es vital por alla.

He dicho virtual, y ha dicho bien, internet es rapido, pero la vida real no tanto, africa aun menos, y los arboles no se plantan instantaneamente, mi arbol tardara un tiempo en tener su representacion en el mundo real, pero no me cabe duda de que lo hara. No solo porque estan las Naciones Unidas detras, si no porque hay gente metida en este proyecto a la que conozco de flickr.com desde hace ya unos añitos.

PS:Vale que tree-nation.com no tiene el diseño Web que nuestros diseñadores aprobarian, ni la arquitectura (PHP5) es la que nos mola por aqui, pero no es eso de lo que va este post.

Una de lenguajes clásicos: el COBOL

Posteado por Jorge Torres Chacón en March 15th, 2007

Últimamente se ha hablado en la empresa de lenguajes de programación clásicos con los que todos crecimos como el Basic o el Turbo Pascal (por los que cierto bastante afecto, todo sea dicho). De todos los clásicos uno de los más persistentes es el COBOL (y a la postre de los más feos), aún utilizado masivamente en grandes empresas que se sienten incapaces de migrar sus mastodónticos sistemas a otros lenguajes, o simplemente obtienen la fiabilidad deseada.

No pretendo dar un curso de COBOL, pero para los más pirados aquí dejo el código del juego del ahorcado que he hecho en COBOL. Pruébalo, funciona:

      * Juego del ahorcado.

000100 IDENTIFICATION DIVISION.
000200 PROGRAM-ID. AHORCADO.

000300 ENVIRONMENT DIVISION.

000400 DATA DIVISION.
000410 WORKING-STORAGE SECTION.
       01  TEMP PIC 9 VALUE 0.
       01  CONT PIC 99 VALUE 0.
       01  CARACTER PIC X VALUE SPACE.
       01  LIFE PIC 9 VALUE 4.
       01  ENCONTRADO PIC 9 VALUE 0.
       01  LONGITUD PIC 9 VALUE 0.
       01  LONGITUD-INICIAL PIC 9 VALUE 0.
       01  SCORE PIC 99 VALUE 0.

       01  CADENA PIC X(9) VALUE SPACES.
      * Copiaremos la cadena origen a una tabla de caracteres.
       01  PALABRA.
           02 ORIGEN OCCURS 9 TIMES PIC X.
      * La palabra de salida.
       01  RESULTADO.
           02 DESTINO OCCURS 9 TIMES PIC X.

000500 PROCEDURE DIVISION.

000700 PROGRAM-BEGIN.

           PERFORM INICIAR-JUEGO.
           PERFORM LIMPIAR-PANTALLA.
           PERFORM PRINCIPAL UNTIL (ENCONTRADO = 1) OR
           (LIFE <= 0) OR (CARACTER = 'Q').
           IF ENCONTRADO = 1
              DISPLAY "Solucion: " PALABRA
              DISPLAY "Has salvado el cuello" LINE 20 COL 30.
           IF LIFE = 0
              DISPLAY "Solucion: " PALABRA
              DISPLAY "Tu cuerpo alimentara los buitres" LINE 20 COL 25
              PERFORM DIBUJAR-PLATAFORMA
              PERFORM DIBUJAR-PERSONAJE.            

001000 PROGRAM-DONE.
001100     STOP RUN.

001100 INICIAR-JUEGO.
           PERFORM LIMPIAR-PANTALLA.
           DISPLAY "Introduzca palabra minuscula (max. 9 car.): ".
           ACCEPT CADENA.

      * Contar caracteres hasta primer espacio (sirve para medir
      * la longitud de la palabra). Como esta variable irá decreciendo
      * salvamos la longitud inicial.
           INSPECT CADENA TALLYING LONGITUD FOR CHARACTERS BEFORE
           INITIAL SPACE.
           MOVE LONGITUD TO LONGITUD-INICIAL.
      * Metemos la palabra en la matriz de caracteres e iniciamos
      * el destino con *.
           MOVE CADENA TO PALABRA.
           PERFORM VARYING CONT FROM 1 BY 1 UNTIL CONT > LONGITUD
              MOVE ‘*’ TO DESTINO(CONT)
           END-PERFORM.
      * Limpiamos pantalla y comienza el juego.

001100 LIMPIAR-PANTALLA.
      * Limpiar pantalla
           PERFORM 25 TIMES
              DISPLAY ” ”
           END-PERFORM.

001100 PRINCIPAL.

           DISPLAY “Salir con ‘Q’ ” LINE 24 COL 1.
           DISPLAY “Adivina la palabra: ” LINE 5 COL 30.
           DISPLAY “SCORE: ” LINE 1 COL 10
           DISPLAY SCORE LINE 1 COL 18
           DISPLAY “VIDA: ” LINE 1 COL 60.
           DISPLAY LIFE LINE 1 COL 67.
           DISPLAY ” “.
           PERFORM DIBUJAR-PLATAFORMA.
           PERFORM DIBUJAR-PERSONAJE.
           DISPLAY RESULTADO LINE 6 COL 30.
           ACCEPT CARACTER LINE 7 COL 30.
           PERFORM CONTAR-OCURRENCIAS.
      * Cuando Longitud a decrecido a 0 es que se han encontrado
      * todos los caracteres.
           IF LONGITUD <= 0
              MOVE 1 TO ENCONTRADO.

001100 CONTAR-OCURRENCIAS.
      * ¿Existe la letra?
           INSPECT CADENA TALLYING TEMP FOR ALL CARACTER.
           IF TEMP > 0
      * Si es así reemplazamos todas sus ocurrencias por ‘-’ para
      * que no vuelva a aparecer y buscamos en la tabla sus posiciones.
              INSPECT CADENA REPLACING ALL CARACTER BY ‘-’
              PERFORM ACTUALIZAR-CADENA
           ELSE
              COMPUTE LIFE = LIFE - 1
           END-IF.
           MOVE 0 TO TEMP.

001100 ACTUALIZAR-CADENA.

           PERFORM VARYING CONT FROM 1 BY 1 UNTIL
           (CONT > LONGITUD-INICIAL)
              IF ORIGEN(CONT) = CARACTER
                 MOVE ORIGEN(CONT) TO DESTINO(CONT)
                 COMPUTE LONGITUD = LONGITUD - 1
                 ADD 1 TO SCORE
              END-IF
           END-PERFORM.

001100 DIBUJAR-PLATAFORMA.
           DISPLAY “|”|” LINE 12 COL 35.
           DISPLAY “|” LINE 13 COL 35.
           DISPLAY “|” LINE 14 COL 35.
           DISPLAY “|” LINE 15 COL 35.
           DISPLAY “|” LINE 16 COL 35.
           DISPLAY “=====” LINE 17 COL 35.
           DISPLAY “=====” LINE 18 COL 35.

001100 DIBUJAR-PERSONAJE.
           IF LIFE < 4
              DISPLAY "" LINE 13 COL 38.
           IF LIFE < 3
              DISPLAY "|" LINE 14 COL 38.
           IF LIFE < 2
              DISPLAY "/" LINE 14 COL 37
              DISPLAY "\" LINE 14 COL 39.
           IF LIFE < 1
              DISPLAY "/" LINE 15 COL 37
              DISPLAY "\" LINE 15 COL 39.

No me digaís que no es bonito…

El valor de Xnoccio.com

Posteado por dbejar en March 15th, 2007

Una chorraplicacion que me he encontrado por ahi…


Xnoccio.com hoy 15-marzo-2007 vale $564.54.
Cuanto vale tu blog?

Francamente, es mucho mas de lo que me esperaba…
Por 564 dolares americanos yo lo vendia ya :)

OutOfMemory error en Maven2 package

Posteado por dbejar en March 15th, 2007

Casi me vuelvo loco intentando encontrar la forma de aumentar la memoria que usa mi maven sobre winXP para hacer un package.

Yo ejecutaba normalmente:


mvn  -Dmaven.test.skip=true package

Y obtenia:


[INFO] ------------------------------------------------------------
[ERROR] BUILD FAILURE
[INFO] ------------------------------------------------------------
[INFO] Compilation failure
Failure executing javac, but could not parse the error: 

The system is out of resources.
Consult the following stack trace for details.
java.lang.OutOfMemoryError: Java heap space 

Failure executing javac, but could not parse the error: 

The system is out of resources.
Consult the following stack trace for details.
java.lang.OutOfMemoryError: Java heap space 

[INFO] ------------------------------------------------------------
[INFO] For more information, run Maven with the -e switch
[INFO] ------------------------------------------------------------

Bueno, pues despues de intentar de todo, lo unico que he conseguido hacer que funcione es modificar el mvn.bat para que incluya -Xmx512m, que como sabreis significa: “set maximum Java heap size to 512MB” …el problema era hacer que maven2 me lo cogiese.
El sitio donde poner esto en el mvn.bat es donde de establece la variable MAVEN_OPTS.

En mi caso la cosa tiene esta pinta:


%MAVEN_JAVA_EXE% %MAVEN_OPTS% "-Xmx512m" -classpath %CLASSWORLDS_JAR%

Tachan!

Espero que esto ayude a alguien a no perder tanto el tiempo…

Tu primera Annotation chispas (II)

Posteado por dbejar en March 5th, 2007

Segunda parte de mi serie dedicada a las Annotations.

Ya teniamos nuestra annotation @Foo creada, y la estabamos declarando en el VO. Ahora vamos a intentar usar de alguna manera esos metodos que habiamos dejado anotados.

Pongamos que por ejemplo queremos hacer un toString del VO, pero solo queremos que se nos pinten las propiedades anotadas, y sus atributos.


package test.absurdo;  

import test.absurdo.vo.AbsurdoVO;  

public class TestAbsurdo {  

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		AbsurdoVO absurdo=new AbsurdoVO();
		absurdo.setBar0(3);
		System.out.println(absurdo);
		System.out.println("fin");
	}
}

La ejecucion de ese codigo evidentemente nos sacara una basura parecida a esta:


test.absurdo.vo.AbsurdoVO@82ba41
fin

Por eso vamos a modificar ligeramente la cabecera de nuestro VO:


package test.absurdo.vo;  

import test.absurdo.annotation.Anotado;
import test.absurdo.annotation.chorranotacion.Foo;  

public class AbsurdoVO extends Anotado{  

[.....]  

Y en Anotado vamos a sobreescribir el metodo toString. El codigo es bastante sencillo de entender sabiendo poquito de Reflection pero aun asi, voy a ponerle un poco de literatura…

Basicamente, marco el metodo toString con la annotation @Override, lo cual no es mandatorio, pero no esta de mas.
En #1 recopilo todos los metodos del VO.(getMethods())
En #2, con un foreach de java5, recorro todos y cada uno de estos metodos.
En #3, recupero la annotation de clase Foo del metodo en cuestion, y en #4 y #5 descarto aquellos metodos que no tienen la annotation @Foo.
Las lineas #6 y #7 las he puesto para simplificar el ejemplo; si el metodo tiene parametros tambien lo descarto, solo tendre en cuenta los metodos que esten anotados con @Foo en los getters. Por tanto, por simplicidad, si hubiesemos puesto @Foo en un setter, no lo tendremos en cuenta.

Quizas el quid de todo este en #8, donde añado a un LikedList de Strings lo que quiero que mas tarde sea la salida del toString, y esto es, en mi caso, annotation.alias() que me devuelve el valor del atributo alias de la annotation @Foo. Si @Foo tuviese un atributo llamado patata, la llamada seria annotation.patata(). No es necesaria ninguna comprobacion para recuperar el atributo alias, ya que tiene un valor por defecto, asi que siempre tiene un valor, pero si no tuviese un valor por defecto, y ademas hubiesemos usado la annotation en algun lugar sin darle ningun valor a alias, entonces saltaria un error en tiempo de compilacion. Por tanto, no es necesario comprobar si la llamada annotation.alias() devuelve null o no. Ademas, en #8, tambien llamo al getter m.invoke(this) que me devolvera el valor de la propiedad. Como ya me he asegurado de que el metodo no tiene parametros, no necesito tampoco comprobaciones adicionales aqui. Ademas, le paso solo un parametro, porque como en java 5, invoke esta definido con var args Object java.lang.reflect.Method.invoke (Object obj, Object… args), una caracteristica de los var args, es que no necesito poner ningun parametro, si todos los argumentos variables son null.

Ya despues de esto solo nos queda recorrer la lista de String y preparar la salida de nuestro toString.


package test.absurdo.annotation;  

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.LinkedList;
import java.util.List;  

import test.absurdo.annotation.chorranotacion.Foo;  

public class Anotado {
	@Override
	public String toString(){
		String output = "";
		List descriptores = new LinkedList();
		Method[] metodos = this.getClass().getMethods();//#1
		for (Method m: metodos){//#2
			Foo annotation = m.getAnnotation(Foo.class);//#3
			if (annotation == null) {//#4
				continue;//#5
			}
			if (m.getParameterTypes().length>0){//#6
				//Por simplicidad,
				//@Foo solo se considera en los getters
				//Pasamos de setters y demas…
				continue;//#7
			}
			try {
				descriptores.add(annotation.alias() +
				” “+m.invoke(this));//#8
			} catch (IllegalArgumentException e) {
				e.printStackTrace();
			} catch (IllegalAccessException e) {  

				e.printStackTrace();
			} catch (InvocationTargetException e) {
				e.printStackTrace();
			}
		}
		// si no hay metodos anotados con @Foo,
		//usar el toString por defecto
		if (descriptores.isEmpty()) {
			output=super.toString();
		}else{
			for (String d : descriptores){
				output=output+ d+ “;”;
			}
		}
		return output;
	}
}

Y ya esta! Tachan! La salida, de la ejecucion de nuestro main ahora sera mucho mas potita:


Bar de tapas 3;Bar de copas 2;Bar que te clavan 5;Foola 8;
fin

Con esto ya deberiamos ser capaces de hacer y usar nuestras propias annotations.

Se pueden usar las annotations sin tener que extender una clase que haga uso de la annotation? Evidentemente si. Todos los dias usamos annotations de Java5, o Hibernate 3.0, en nuestros VOs, sin tener que hacer ningun extends especifico.

Lo dejo para una tercera parte…

Haciendo simple RMI

Posteado por Félix García Borrego en March 5th, 2007

Estamos realizando una integración entre dos plataformas, y dado que, ambas son Java, se ejecutarán en el mismo segmento de red y necesitamos una integración fuerte, hemos optado en esta ocasión por usar RMI en detrimento de SOAP.

Hasta ahí, todo bien, el problema surge cuando las aplicaciones podrian ser desplegadas en cualquier servidor de aplicaciones. Cada servidor de aplicaciones tiene su propio mecanismo para la publicación de RMI( Jboss, Oc4j,Geronimo, IBM WebShare,Sun Java System Application Server …) que suele simplificar las cosas, pero que en nuestro caso dificulta la configuración del sistema.

Una posible solución es optar por no utilizar el mecanismo que ofrece el servidor de aplicaciones y crear de forma programática el registro RMI, esta opción requiere un poco mas de esfuerzo pero nos aisla de los problemas que puedan surgir al desplegar la aplicación.

Las siguentes lineas de código muestran como activar un registro RMI sin tener que utilizar los mecanismos que ofrecen Jboss, Oc4j o el comando rmiregistry

Registry registry = LocateRegistry.createRegistry(5432);

// creamos la instancia del Servidor
ServerRMI serverRMI=new ServerRMI();

// publicamos el servidor en el registro
registry.bind(”test”, serverRMI);

La solución es realmente muy sencilla, os dejo un ejemplo cliente-servidor RMI.

Ejemplo RMI sencillo

Usando VelocityContext: OutOfMemoryError: Java heap space

Posteado por dbejar en March 4th, 2007

Ojo con el uso del VelocityContext.
Parece que el recolector de basura no funciona todo lo bien que deberia, al menos en Java5.
Hace ya tiempo tuvimos un problema de consumo excesivo de memoria al reutilizar una List en el mismo objeto VelocityContext
.
Digamos que, por ejemplo, teniamos en una plantilla vm, el siguiente codigo:


#foreach $absurdo in $absurdos
 private String tremendo${absurdo};
#end

Esa plantilla la queriamos usar para distintas cosas pasandole disntinta informacion en $absurdos. Asi que reutilizabamos nuestro objecto VelocityContext, modificandole el valor del contexto absurdos.
Algo como esto:


VelocityContext vcontext=new VelocityContext();
List ls=new LinkedList();
//Puebla ls
for (int j=0; j<900000; j++){
	ls.add(”Foo”+j);
}
vcontext.put(”absurdos”, ls); 

//Escribimos el fichero usando la plantilla vm
……
//Y reutilizamos
ls=new LinkedList();
//Puebla ls
for (int j=0; j<900000; j++){
	ls.add(”Bar”+j);
}
vcontext.put(”absurdos”, ls);
//Escribimos un nuevo fichero usando la plantilla vm
……

Bien, pues parece que el recolector de basura no hace su trabajo adecuadamente, al menos de manera automatica….y el consumo de memoria se nos disparaba…

Un pequeño programa cutrecillo para demostrar el problema (Con JDK 1.5.10).


package test.absurdo; 

import java.util.LinkedList;
import java.util.List;
import org.apache.velocity.VelocityContext; 

public class TestAbsurdo { 

	private static final
	String murcielago="El veloz murciélago hindú comía feliz"+
	" cardillo y kiwi."; 

	private static long mem0,mem1,mem2; 

	public static long usoMem(){
		return Runtime.getRuntime().totalMemory() -
			Runtime.getRuntime().freeMemory();
	}
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		VelocityContext vcontext=new VelocityContext();
		List ls=new LinkedList();
		mem0=usoMem();
		for(int i=1; i<3; i++){
			for (int j=0; j<900000; j++){
				ls.add(murcielago);
			}
			vcontext.put(”testabsurdo”, ls);
			mem1=usoMem();
			System.out.println(”En la iteracion=”+i+” mem=”+(mem1-mem0));
			ls=new LinkedList();
			mem2=usoMem();
			System.out.println(”Despues del new, mem=”+(mem2-mem0));
		}
		System.out.println(”fin”);
	}
}

La salida por consola es:


En la iteracion=1 mem=21403744
Despues del new, mem=21446016
En la iteracion=2 mem=43010320
Despues del new, mem=43010320
fin

Preocupante.

En nuestro caso nos comia la memoria hasta desbordar el heap, y romper la ejecucion.

Curisomente, si forzamos el recolector de basurar, el resultado es muy distinto:


public static void main(String[] args) {
VelocityContext vcontext=new VelocityContext();
List ls=new LinkedList();
mem0=usoMem();
for(int i=1; i<3; i++){
	for (int j=0; j<900000; j++){
		ls.add(murcielago);
	}
	vcontext.put(”testabsurdo”, ls);
	mem1=usoMem();
	System.out.println(”En la iteracion=”+i+” mem=”+(mem1-mem0));
	ls=new LinkedList(); 

//FORZAMOS GARBAGE COLLECTION
System.gc();System.gc();System.gc();System.gc();
System.gc();System.gc();System.gc();System.gc();

	mem2=usoMem();
	System.out.println(”Despues del new, mem=”+(mem2-mem0));
	}
System.out.println(”fin”);
}

La salida por consola es:


En la iteracion=1 mem=21403744
Despues del new, mem=21402928
En la iteracion=2 mem=43079200
Despues del new, mem=21402928
fin

Lo que demuestra que el problema esta en la gestion del recolector de basuras.

En cualquier caso, como no nos mola nada programar la gestion de la maquina virtual, optamos por otra solucion, menos agresiva. Y aun mas eficaz. Remplazamos las posible llamada al recolector de basura, y recargamos todo lo que necesitamos en el context.


public static void main(String[] args) {
VelocityContext vcontext=new VelocityContext();
List ls=new LinkedList();
mem0=usoMem();
for(int i=1; i<3; i++){
	for (int j=0; j<900000; j++){
		ls.add(murcielago);
	}
	vcontext.put(”testabsurdo”, ls);
	mem1=usoMem();
	System.out.println(”En la iteracion=”+i+” mem=”+(mem1-mem0));
	ls=new LinkedList(); 

//RESET VelocityContext
context=null;
context = new VelocityContext(); 

	mem2=usoMem();
	System.out.println(”Despues del new, mem=”+(mem2-mem0));
	}
System.out.println(”fin”);
}

Con salida:


En la iteracion=1 mem=21403744
Despues del new y el reset, mem=21446016
En la iteracion=2 mem=21617248
Despues del new y el reset, mem=21617248
fin

Quizas, lo que debiamos haber hecho desde un principio.

ODIO Windows Vista

Posteado por Javier Echeverría Usua en March 3rd, 2007

Recomiendo encarecidamente a todo el que lea esto y sea desarrollador Java, que no haga el primo y se pille un ordenador con Windows Vista. Esta vez sí que han conseguido evangelizarme a Linux, aunque tendré que ver cómo hacerlo, porque me obligó a convertir el disco duro a “dinámico” para poder hacerle una segunda partición para datos… y no sé qué tal lo llevará Ubuntu.

El motivo de mi nuevo (enésimo) disgusto es que OFICIALMENTE todavía no hay soporte del cliente de Oracle con Windows Vista. Y menos con la versión Business que tenemos en nuestros portátiles. Tendremos que esperar a que Oracle libere la versión 10.2.0.3; por desgracia, Oracle sólo da en estos momentos como disponible la 10.2.0.1 en su web. Parece ser que en Metalink (https://metalink.oracle.com/) existe la versión 10.2.0.3 del instalador, y que se puede hacer un truquito (http://cshay.blogspot.com/) para hacerlo funcionar… pero claro, Metalink sólo está disponible si dispones de un servicio de soporte para Oracle.

Desastroso lo de los ***ones de Redmond.