La única opción real es (desafortunadamente) terminar la JVM lo antes posible.
Dado que probablemente no pueda cambiar todo su código para detectar el error y responder. Si no confías en el OnOutOfMemoryError
(Me pregunto por qué no debería usar vfork que usa Java 8 y funciona en Windows), al menos puede activar un volcado de almacenamiento dinámico y monitorear externamente esos archivos:
java .... -XX:+HeapDumpOnOutOfMemoryError "-XX:OnOutOfMemoryError=kill %p"
Después de experimentar con esto durante bastante tiempo, esta es la solución que funcionó para nosotros:
- En la JVM generada, captura un
OutOfMemoryError
y salga inmediatamente, señalando la condición de falta de memoria con un código de salida a la JVM del controlador. - En la JVM generada, verifique periódicamente la cantidad de memoria consumida del
Runtime
actual . Cuando la cantidad de memoria utilizada esté cerca de ser crítica, cree un archivo de indicadores que señale la condición de falta de memoria a la JVM del controlador. Si nos recuperamos de esta condición y salimos normalmente, elimine ese archivo antes de salir. - Después de que la JVM de control se une a la JVM bifurcada, verifica el código de salida generado en el paso (1) y el archivo de marca generado en el paso (2). Además de eso, comprueba si el archivo
hs_err_pidXXX.log
existe y contiene la línea "Error de memoria insuficiente". (Este archivo es generado por Java en caso de que falle).
Solo después de implementar todas esas comprobaciones pudimos manejar todos los casos en los que la JVM bifurcada se quedó sin memoria. Creemos que desde entonces, no hemos perdido un caso en el que esto sucediera.
La bandera java -XX:OnOutOfMemoryError
no se usó debido al problema de la bifurcación, y -XX:+HeapDumpOnOutOfMemoryError
no se usó porque un volcado de montón es más de lo que necesitamos.
La solución ciertamente no es la pieza de código más elegante jamás escrita, pero hizo el trabajo por nosotros.