Jedinou skutečnou možností je (bohužel) ukončit JVM co nejdříve.
Protože pravděpodobně nemůžete změnit celý svůj kód, abyste zachytili chybu a odpověděli. Pokud nedůvěřujete OnOutOfMemoryError
(Zajímalo by mě, proč by to nemělo používat vfork, který používá Java 8 a funguje na Windows), můžete alespoň spustit heapdump a externě sledovat tyto soubory:
java .... -XX:+HeapDumpOnOutOfMemoryError "-XX:OnOutOfMemoryError=kill %p"
Poté, co jsme s tím nějakou dobu experimentovali, toto je řešení, které pro nás fungovalo:
- Ve vytvořeném JVM zachyťte
OutOfMemoryError
a okamžitě ukončete, což signalizuje stav nedostatku paměti pomocí výstupního kódu řídicímu JVM. - Ve vytvořeném JVM pravidelně kontrolujte množství spotřebované paměti aktuálního
Runtime
. Když se množství použité paměti blíží kritické hodnotě, vytvořte soubor příznaku, který signalizuje stav nedostatku paměti do JVM řadiče. Pokud se z tohoto stavu zotavíme a skončíme normálně, před ukončením tento soubor smažte. - Poté, co se řídící JVM připojí k rozvětvenému JVM, zkontroluje výstupní kód vygenerovaný v kroku (1) a soubor příznaků vygenerovaný v kroku (2). Kromě toho kontroluje, zda je soubor
hs_err_pidXXX.log
existuje a obsahuje řádek "Chyba nedostatku paměti". (Tento soubor vygeneruje Java pro případ, že dojde k jeho zhroucení.)
Teprve po implementaci všech těchto kontrol jsme byli schopni zvládnout všechny případy, kdy rozvětvenému JVM došla paměť. Věříme, že od té doby nám neunikl případ, kdy se to stalo.
Java příznak -XX:OnOutOfMemoryError
nebyl použit kvůli problému s rozvětvením a -XX:+HeapDumpOnOutOfMemoryError
nebyl použit, protože výpis haldy je více, než potřebujeme.
Řešení rozhodně není tím nejelegantnějším kouskem kódu, jaký byl kdy napsán, ale udělal to za nás.