Una aplicación que recientemente hemos comenzado a bloquear de forma esporádica con un mensaje sobre "java.lang.OutOfMemoryError: 8589934608 bytes solicitados para Chunk :: new. ¿Espacio fuera de intercambio?".Java JIT Compiler causando OutOfMemoryError
He mirado alrededor en la red, y en todas partes se limitan a sugerencias
- volver a una versión anterior de Java
- violín con la configuración de memoria
- uso de los clientes en lugar de modo de servidor
Volver a una versión anterior implica que el nuevo Java tiene un error, pero no he visto ninguna indicación de eso. La memoria no es un problema en absoluto; el servidor tiene 32 GB disponibles, y Xmx está configurado a 20, mientras que Xms es 10. No veo que la JVM se quede sin los 12 GB restantes (menos la cantidad otorgada a otros pocos procesos en la máquina). Y estamos atrapados con el modo de servidor debido a la naturaleza de la aplicación y el entorno.
Cuando miro la memoria y el uso de la CPU para la aplicación, veo uso de memoria constante durante todo el día, pero de repente justo antes de que muera el uso de la CPU aumenta al 100% y el uso de memoria va de X a X + 2GB, a X + 4GB, a (a veces) X + 8GB, a la muerte de JVM. Parece que tal vez haya un ciclo de ajuste de matriz repetido en la compilación de JIT.
Ahora he visto que se produce el error con la solicitud de 8GB anterior y también las solicitudes de 16 GB. En todos los casos, el método que se compila cuando esto sucede es el mismo. Es un método simple que tiene bucles no anidados, sin recurrencia, y utiliza métodos en objetos que devuelven campos de miembros estáticos o campos de miembros de instancias directamente con pocos cálculos.
así que tengo 2 preguntas:
- ¿Alguien tiene alguna sugerencia?
- ¿Puedo probar si hay un problema al compilar este método específico en un entorno de prueba, sin ejecutar toda la aplicación, invocando el compilador JIT directamente? ¿O debería iniciar la aplicación y decirle que compile métodos después de un recuento de llamadas mucho más pequeño (como 2) para obligarlo a compilar el método casi instantáneamente en lugar de en un punto aleatorio del día?
@StephenC
La JVM es 1.6.0_20 (anteriormente 1.6.0_0), que se ejecuta en Solaris. Sé que es la compilación la que está causando un problema por un par de razones.
ps
en los segundos que conducen a ella muestra que un hilo de java con id correspondiente a la rosca compilador (de jstack) está tomando el 100% del tiempo de CPUjstack
muestra el problema está enJavaThread "CompilerThread1" daemon [_thread_in_native, id=34, ...]
El método mencionado en jstack
es siempre el mismo, y es uno que escribimos. Si observa el resultado de la muestra jstack
sabrá a qué me refiero, pero por razones obvias no puedo proporcionar ejemplos de código o nombres de archivo. Diré que es un método muy simple. Essentiall un puñado de comprobaciones nulas, 2 para bucles que hacen controles de igualdad y posiblemente asignar valores, y algunas llamadas a métodos simples después.Con todo, tal vez 40 líneas de código.
Este problema ha sucedido 2 veces en 2 semanas, aunque la aplicación se ejecuta todos los días y se reinicia diariamente. Además, la aplicación no estaba bajo carga pesada en ninguno de estos momentos.
Sería útil si dijera qué versión de JVM y nivel de parche está utilizando (y qué era antes) y cuál es su plataforma de sistema operativo/hardware. Además, por qué ha concluido que el problema está sucediendo durante la compilación de JIT, cómo ha descubierto el método que se está compilando ... y cómo se ve el código del método. –
¿Encontró una solución satisfactoria? –
Lo siento por la * muy * respuesta tardía: he marcado la respuesta ahora – Phil