2010-11-10 19 views
5

Tengo un proceso crítico ejecutándose en java (1.6), con un gancho de apagado registrado. En algunos casos donde recibo un problema de OOM (más detalles a continuación sobre el tema), el proceso se detiene de repente, no obtengo ninguno de mis registros, mi captura (Throable x) no capta la excepción.jvm: ¿es posible descubrir que el proceso se está cerrando debido a un OOM mientras está en el gancho de apagado?

Pero el gancho de cierre funciona. Entonces, si hubiera una manera de saber que el proceso se va a cerrar debido a una desagradable OOM, podría registrar la información necesaria antes de salir.

¿Hay alguna manera de hacerlo?

Acerca de OOM: No estoy seguro de cuál es la excepción porque, como he dicho, no queda atrapado. Sé que es un OOM porque comienzo el proceso con

-XX:+HeapDumpOnOutOfMemoryError 

y obtengo un archivo de volcado de almacenamiento dinámico. En otros casos, se detecta una excepción, y se trata de un ava.lang.OutOfMemoryError: se excedió el límite superior del GC. Pero no estoy seguro de que siempre sea este el caso.

EDIT:

En caso de que no está claro: No estoy tratando de evitar la OOM, ya que puede suceder por razones válidas en algún escenario, sólo quiero para asegurarse de que está claro en el archivos de registro de aplicación

Mi pregunta es: ¿es posible descubrir que el proceso se está cerrando debido a un OOM mientras está en el gancho de apagado?

Necesito hacer esto mediante programación y desde el mismo proceso.

Por ahora, el mejor enfoque es ver si existe un archivo de volcado del montón java_pid_pid de process_.hprof (sé el pid) con fecha reciente y deducir que había un OOM. Supongo que podría probar Runtime.getRuntime(). FreeMemory() e informar el problema si la memoria disponible es muy baja, pero no estoy seguro de qué tan confiable es, quizás cuando el proceso se apaga ya ha liberado mucha memoria, el enfoque de arriba es lo mejor, creo.

+0

Entonces su pregunta es: "¿Qué sucede?" - ¿derecho? – dacwe

+0

No se enfade con la pregunta, pero ¿capta (Excepción x) o captura (Throable x) como OOM es Throable, estoy seguro de que lo sabe y probablemente no sea atrapado si sucede, pero aún así vale la pena verificar ... –

+0

como menciono (tal vez no está claro, voy a editar de nuevo) Tengo una trampa (Throable x) no está teniendo efecto. gracias – Persimmonium

Respuesta

3

Los OOM son complicados porque si JVM está fuera de memoria, es posible que no ejecute el código de manejo de excepciones debido a que se está lanzando un OOM nuevo.

Pruebe la configuración default uncaught exception handler. Capturará todas las excepciones no detectadas.

+0

Esto es nuevo para mí. ¿Tienes referencias? En mi experiencia, OOME es un error normal lanzado, propagado y atrapado como cualquier error. Por supuesto, podría ocurrir que durante el manejo del error, ocurra otro OOME. –

+0

Exactamente. No estaba lo suficientemente claro: podría arrojar un nuevo OOM y no ejecutar el código que se pretendía. Edité la publicación. –

2

Probablemente pueda ejecutar otro proceso que supervise el archivo de registro para OOE (o monitoree si el proceso se cancela) y luego reinicie el proceso.

Tal vez sea más apropiado poner su aplicación como Unix deamon o servicio de Windows.

Pero, ¿qué hay de investigar la fuga de memoria con herramientas de creación de perfiles en su lugar?

jvisualvm es una buena

0

puede (técnicamente) captura OutOfMemoryErrors, pero no está seguro de que pueda ejecutar el código en el bloque catch, si no queda memoria.

Quizás valga la pena intentarlo (1) atrapar el OOM, (2) desencadenar la recolección de elementos no utilizados (System.gc()) e intentar escribir algo para iniciar sesión o para la consola. Sin garantía pero no romperá nada.

+0

Por lo que tengo entendido, System.gc() debería llamarse automáticamente antes que OOM, el problema es que después o durante el gc OOM aún ocupa –

0

Debería resolver el problema en lugar de intentar compensarlo.

El volcado del montón le mostrará los tipos de objeto que consumen la mayor cantidad de memoria. Debería poder averiguar dónde se asignan esos objetos, o por qué se quedan después de que deberían descartarse.

En cuanto al error específico que está recibiendo, eche un vistazo a esta pregunta ASÍ: Error java.lang.OutOfMemoryError: GC overhead limit exceeded - parece que la solución más simple será aumentar su tamaño de almacenamiento dinámico.

+0

el problema es que los registros no muestran nada sobre el problema OOM, entonces estoy tratando de resolverlo. El OOM puede ocurrir como algunos casos de uso válidos y solo necesito señalizarlo en los archivos de registro. – Persimmonium

+0

@raticulin - No, OOM no * puede * suceder en casos de uso "válidos". En cualquier aplicación Si tiene casos de uso que pueden exceder la cantidad de memoria disponible, debe reconocer eso antes de que realmente se quede sin memoria. Tal vez debería hacer una pregunta sobre cómo lograr eso ... – Anon

+0

Y una sugerencia: Las referencias suaves son una forma de escribir código que maneja con gracia una situación de "necesitar demasiada memoria". – Anon

0

Una vez más, usar jvisualvm (JDK 6, en la carpeta bin) como sugerencia de otros u otras herramientas de creación de perfiles es la mejor manera de resolver el problema en lugar de manejarlo, pero suponiendo que investigará por separado las causas OOM e intente para erradicarlos, consideraría hacer el siguiente POC, (vea también la respuesta de Alois)

¿Qué tal si ejecuta un proceso Java que envuelva la llamada del proceso de lanzamiento OOM?

Se puede tomar cualquier resultado que se está enviando a la corriente de salida del proceso que se llama, y ​​ver si hay un rastro código de salida constante/pila se puede utilizar para identificar Ooms

Estoy seguro de que hay más se acerca, pero esto me parece un buen punto de partida programático

Cuestiones relacionadas