L'unica vera opzione è (sfortunatamente) terminare la JVM il prima possibile.
Dal momento che probabilmente non puoi modificare tutto il tuo codice per rilevare l'errore e rispondere. Se non ti fidi del OnOutOfMemoryError
(Mi chiedo perché non dovrebbe usare vfork che è usato da Java 8 e funziona su Windows), puoi almeno attivare un heapdump e monitorare esternamente quei file:
java .... -XX:+HeapDumpOnOutOfMemoryError "-XX:OnOutOfMemoryError=kill %p"
Dopo aver sperimentato questo per un po' di tempo, questa è la soluzione che ha funzionato per noi:
- Nella JVM generata, rileva un
OutOfMemoryError
ed esci immediatamente, segnalando la condizione di memoria esaurita con un codice di uscita alla JVM del controller. - Nella JVM generata, controlla periodicamente la quantità di memoria consumata dell'attuale
Runtime
. Quando la quantità di memoria utilizzata è prossima al valore critico, creare un file flag che segnali la condizione di memoria insufficiente alla JVM del controller. Se ci riprendiamo da questa condizione e usciamo normalmente, cancella quel file prima di uscire. - Dopo che la JVM di controllo si è unita alla JVM biforcuta, controlla il codice di uscita generato nel passaggio (1) e il file flag generato nel passaggio (2). Inoltre, controlla se il file
hs_err_pidXXX.log
esiste e contiene la riga "Out of Memory Error". (Questo file è generato da java in caso di crash.)
Solo dopo aver implementato tutti questi controlli siamo stati in grado di gestire tutti i casi in cui la JVM biforcuta ha esaurito la memoria. Riteniamo che da allora non ci siamo persi un caso in cui ciò è accaduto.
Il flag java -XX:OnOutOfMemoryError
non è stato utilizzato a causa del problema del fork e -XX:+HeapDumpOnOutOfMemoryError
non è stato utilizzato perché un dump dell'heap è più di quello di cui abbiamo bisogno.
La soluzione non è certamente il pezzo di codice più elegante mai scritto, ma ha svolto il lavoro per noi.