Extrañando a los recolectores de basura de mi barrio.

Me pasé toda la semana pasada trabajando con ObjectiveC, prestando muchísima atención al código, especialmente a la declaración de variables, para no ir dejando memory leaks desparramados por ahí. A buena hora me vengo a enterar que ObjetiveC es muy sensible a los memory leaks. Para un Java adicto GC dependiente como yo, esto de andar contando la cantidad de referencias a un objeto para luego "destruir" (liberar) las variables a mano, es una experiencia completamente nueva.

Después de una semana con ObjetiveC el sábado retome el trabajo con Trails, preparando lo que será el codebase para Trails 2.0.x (el ".x" del final es a propósito para que no parezca un buzzword). La nueva versión de Trails estará basada en Tapestry5 y como este trae su propio contenedor IoC la mayor parte del trabajo fue portar servicios, beans y configuración de Spring al nuevo Tapestry5 IoC. Una de las principales diferencias entre los dos contenedores es que la inyección de dependencias en Tapestry5 se realiza por contructor en lugar de por setters. Esta fue la principal razón que impidió que el port de un IoC a otro fuera completamente automático.

Mientras reescribía los constructores noté que muchos de los servicios tenían variables de instancia con referencias a otros servicios que ahora ya no era necesario mantener como variable de instancia. Saltó la alarma:

POSIBLE MEMORY LEAK!!!! POSIBLE MEMORY LEAK!!! POSIBLE MEMORY LEAK!!!!.

Estas variables de instancia tranquilamente podían convertirse a variables internas de métodos (constructores) o simplemente eliminarse. Como consecuencia de esta reducción en variables de instancia se reduce considerablemente la cuenta total de referencias de instancias de varios de los servicios. Llegando en varias ocasiones a tener servicios procesados por el GC y eliminados completamente de la memoria.

La conclusión final es que muchos de los servicios de Spring configurados con "init-method" o que utilizan afterPropertiesSet(), o algún mecanismo similar, terminan conteniendo referencias a servicios que solo son necesarios durante bootstrap y por ende aumentando la cuenta de referencias de esos objetos que no son necesarios para continuar con la ejecución de la aplicación.

Soy consiente de que en un entorno clásico de IoC (Tapestry, Spring o cualquiera), los males provenientes pura y exclusivamente de mantener estos objetos en memoria son despreciables y que seguramente se podría lograr una reducción similar en Spring rediseñando los servicios. Pero este post no se trata de eso, este post es simplemente una reflexión sobre lo que damos por sentado los Java adictos GC dependientes como yo.