Esta es una pila de memoria (sirve como caché) que consiste en nada más que una ConcurrentHashMap estática (CHM).Memoria Totalmente utilizada por Java ConcurrentHashMap (en Tomcat)
Todos los datos de solicitud HTTP entrantes se almacenan en este ConcurrentHashMap. Y hay un proceso de planificador asynch que toma los datos del mismo ConcurrentHashMap y elimina el valor clave después de almacenarlos en la base de datos.
Este sistema funciona muy bien y sin problemas, pero sólo descubre bajo criterios siguientes, la memoria se utiliza plenamente (2,5 GB) y se tomó todo el tiempo de CPU para realizar GC:
-concurrent http golpe de 1000/s
-mantener el mismo hit simultáneo durante un período de 15 minutos
El proceso de asincronización registra el tamaño restante del CHM cada vez que se escribe en la base de datos. El CHM.size() se mantiene alrededor de Min: 300 a Max: 3500
Pensé que hay una pérdida de memoria en esta aplicación. entonces usé Eclipse MAT para mirar el Heap Dump. Después de ejecutar el Informe del sospechoso, que me dieron estos comentarios de MAT:
Una instancia de "org.apache.catalina.session.StandardManager" cargados por "org.apache.catalina.loader.StandardClassLoader @ 0x853f0280" ocupa 2135429456 (94.76%) bytes. La memoria se acumula en una instancia de "java.util.concurrent.ConcurrentHashMap $ Segment []" cargado por "".
3,646,166 instances of java.util.concurrent.ConcurrentHashMap$Segment retain >= 2,135,429,456 bytes.
y
Length # Objects Shallow Heap Retained Heap
0 3,646,166 482,015,968 >= 2,135,429,456
La longitud 0 por encima de i traduzco registro de longitud como vacío en el interior del CHM (cada vez CHM.remove() método i llamada). Es consistente con el número de registro dentro de la base de datos, 3,646,166 registros estaba dentro de la base de datos cuando este vertedero se creó
El escenario extraño es: si detengo la prueba de esfuerzo, la utilización de la memoria de pila liberará gradualmente a 25MB. Esto lleva entre 30 y 45 minutos. He vuelto a simular esta aplicación y las curvas es similar a la gráfica VisualVM a continuación:
Heres las preguntas:
1) ¿Esto se parece a una pérdida de memoria?
2) Cada llamada de eliminación remove(Object key, Object value)
para eliminar un <key:value>
de CHM, ¿ese objeto eliminado obtiene GC?
3) ¿Esto tiene algo que ver con la configuración del GC? He agregado los siguientes parámetros de GC pero sin ayuda:
-XX:+UseParallelGC
-XX:+UseParallelOldGC
-XX:GCTimeRatio=19
-XX:+PrintGCTimeStamps
-XX:ParallelGCThreads=6
-verbose:gc
4) Cualquier idea para resolver esto es muy apreciada. :)
NUEVO 5) ¿Podría ser posible porque todas mis referencias son referencias difíciles? Según tengo entendido, mientras la sesión HTTP finalice, todas las variables que no sean estáticas están ahora disponibles para GC.
NUEVO Nota He intentado reemplazar el CHM con ehcache 2.2.0, pero me sale el mismo problema OutOfMemoryException. supongo que ehcache también está usando ConcurrentHashMap.
servidor Spec:
núcleo -Xeon Quad, 8 hilos.
memoria -4GB
-Windows 2008 R2
-Tomcat 6.0.29
¿Cuán difícil sería reemplazar el mapa hash con una instancia de EhCache? Estas bibliotecas están optimizadas para este tipo de tareas. –
Por el momento tratamos de no cambiar tanto al código existente porque aún no hemos analizado el impacto. EhCache fue inicialmente parte de la consideración, pero de alguna manera no se eligió como la opción de implementación. – Reusable