Java Enterprise usa mucha memoria

Hola:

Estoy pensando en mi grar mis aplicaciones al j2ee, y me descargué la versión empresarial de java del sitio de sun. Lo instalé como indican los tutoriales y me programé un sistema-juguete que intercambia mensajes entre el cliente y el componente servidor. Los resultados no fueron satisfactorios, principalmente, por que al contrario de lo que esperaba, el uso de memoria es muy disparado. La aplicación servidor llegua a los 170 MB y sólo hace intercambio de mensajes; no quiero ni pensar a cuanto ha de llegar cuando le monte toda a infraestructura empresarial.

Antes, probé el RMI de java, con mejores resultados, aunque no los deseados. Para cada cliente, el servidor podría llegar a consumir unos 80 MB, llegado al punto máximo estimado de carga de trabajo.

¿Esto es así siempre en la versión empresarial de java? ¿consume una cantidad constante de memoria?

Voy a montar parte de la infraestructura empresarial, para ver como se comporta, si crece mucho o si se queda más o menos proporcional. Si la cosa se pone muy fea, creo que java no me va a ayudar en esto :D

Opciones de visualización de comentarios

Seleccione la forma que prefiera para mostrar los comentarios y haga clic en «Guardar las opciones» para activar los cambios.
Imagen de ezamudio

Memoria J2EE

El problema es que estas pensando en que toda esa memoria se esta yendo en tu codigo y no es asi. Si levantas por ejemplo JBoss o algun otro contenedor con la configuracion default, puedes pensar "no esta haciendo nada, no le he puesto nada, y esta ocupando mucha memoria". El problema esta en que la configuracion default trae algunos servicios... por ejemplo JBoss arranca una mini base de datos cuyo nombre no recuerdo ahora, lee algunas cosas de ahi usando Hibernate, prepara un servicio de mail (sin configurar, y no sirve de hecho asi como viene, pero esta corriendo), un servicio de mensajeria, viene por ahi un datasource, arranca el tomcat, etc etc etc todos los servicios basicos estan corriendo aunque no hagan nada.

La idea de J2EE es que tienes todos esos servicios a tu disposicion. Cuando desarrollas ya algo en particular y sobre todo cuando vas a poner algo en produccion, entonces configuras bien tu contenedor J2EE para que solamente tenga los servicios que necesitas y nada adicional.

En cuanto a RMI, no lo considero muy eficiente tampoco para mensajeo entre aplicaciones cliente-servidor cuando hay muchos clientes; es mejor usar algun otro protocolo, abrir tus propios sockets y enviar los datos que necesitas, aunque es mas engorroso.

En mi experiencia, cuando un contenedor J2EE levanta, consume bastante recursos, pero cuando empiezan a llegar las peticiones de los clientes ya no crece tanto la memoria, si tu aplicacion esta bien optimizada (obviamente si en tu codigo tienes algo que se trae cien mil registros a memoria, entonces vas a consumir bastante memoria pero eso ya es algo de tu codigo).

eZL

Given the choice of dancing pigs and security, users will choose dancing pigs, every single time.
Steve Riley

Alternativa al contenedor de aplicaciones de Sun

En efecto, el contenedor de aplicaciones de jee consume una alta cantidad de recursos. Te recomiendo que pruebes con Apache Tomcat como contenedor, pues te aseguras que sólo tienes el servicio de "contención" de las aplicaciones y nada más. Además, Tomcat trae algunas bibliotecas "nativas" que aceleran enormemente los procesos de carga (esa opción existe en el instalador de windows. No he tenido tiempo de revisar en linux si tiene también las bibliotecas esas).

Apache Tomcat se puede descargar de http://tomcat.apache.org

optimizar el funcionamiento servidor JEE5

Es cierto que cualquier implementación de JEE5 consume demasiados recursos, pero hay maneras de optimizar un poco su eficiendia, como por ejemplo aumentando la cantidad de hilos y la cola de mensajes y/o aumentando la memoria mínima del heap(todo esto en la consola de administración, al menos de glasssfish).
OJO, estas soluciones no ayudan que consuma menos memoria, igual necesitarás una buena cantidad de ram en tu maquina, pero mejorarás en eficiencia.
Otra cosa es que en tu aplicación ayude un poco al recolector de basura poniendo a null todas las referencias que dejas de usar, y sobreescribe el metodo finalize() de las clases que sabes que instancias varias veces(las que llames en los métodos de los servlets sobre todo) y en ese método pones a null todas las referencias de los campos de tu clase.
Con el tiempo me he dado cuenta que no se debe tener demasiada fe en el recolector de basura, hay que darle una mano, y de vez en cuando llamarlo explicitamente con System.gc(), pero ten en cuenta que ahí no lo llamas como tal, sino que le pides por favor que se inicie, si la jvm entiende que no es momento no lo arrancará.