Este artículo es un anexo del artículo principal Java Dark Memory, para aportar detalle sobre este espacio concreto de memoria. En el artículo principal nos centramos en la observabilidad de espacios de memoria menos conocidos y más problemáticos.
Índice
1. ¿Qué es?
Espacio de memoria utilizado por la JVM guardar información de la ejecución de cada uno de los hilos creados por un proceso java:
- Variables locales o intermedias
- Punteros a métodos llamados
- Pila de ejecución: el stack del thread
- ThreadLocal variables
Cada hilo tiene su propio Stack y la propia JVM utiliza hilos para su ejecución, como mínimo el hilo pricipal o main
.
Es habitual que los frameworks y librerías utilizadas creen pools de threads para su reutilización a través del API ThreadExecutor.
2. Observabilidad
- Con NMT podemos ver la cantidad de memoria virtual y residente/comiteada de todo el espacio, es decir, la suma de lo que ocupan todos nuestros en ejecución en un momento dado.
- Con JMX y Mbeans podemos consultar información sobre pools y su estado.
- Con metricas Prometheus, podemos ver el número total de hilos, aunque no la memoria utilizada.
- Con herramientas como Memory Analyzer (MAT), basadas en Eclipse, podemos obtener información detallada tras un HeapDump o un CoreDump.
3. Límites
-
Se puede establecer el tamaño máximo del stack por hilo, a través del flag
-Xss
. Por defecto este valor es de 1MB, que el tamaño máximo que alcanzará un stack individual. -
Sin embargo no se puede establecer máximo número de hilos ni tamaño máximo de esta zona, a través de flags de la JVM.
-
Pro sí podemos mediante configuración (properties) de cada framework o librería, establecer el tamaño máximo de los diferentes pools de threads, de modo que podemos calcular el límite máximo, sabiendo que cada stack ocupará 1MB.
Por ejemplo, si estamos creando una aplicación web con Spring Boot, probablemente utilizaremos Undertow como implementación non-blocking de HTTPServer y ServletServer. La documentación de Undertow nos permite estas dos configuraciones:
-
server.undertow.threads.io: Número de I/O threads a crear. El valor por defecto es derivado del número de CPUs disponibles..
-
server.undertow.threads.worker: Número de worker threads. El valor por defecto es 8 veces el número de I/O threads.
4. Consideraciones
Como vemos con más detalle en el artículo principal Java Dark Memory, los DirectBuffers utilizados por los threads y la caché por thread de buffers (bufferpool), introducen una problemática adicional, reservando memoria fuera del espacio de threads y los stacks, en zonas de difícil observabilidad. La relación entre direct buffers y threads es uno de los principales problemas de la memoria oscura.
Es vital conocer cuántol pools de threads utilizan las aplicaciones que creemos. Para ello debemos estudiar los frameworks y librerías que utilizamos directa o indirectamente, para poder configurar y limitar los tamaños de estos pools. La suma total de los pools nos indicará el tamaño total de este espacio.
暂无评论内容