Satu-satunya pilihan nyata adalah (sayangnya) menghentikan JVM sesegera mungkin.
Karena Anda mungkin tidak dapat mengubah semua kode Anda untuk menangkap kesalahan dan merespons. Jika Anda tidak mempercayai OnOutOfMemoryError
(Saya bertanya-tanya mengapa itu tidak boleh menggunakan vfork yang digunakan oleh Java 8, dan berfungsi pada Windows), Anda setidaknya dapat memicu heapdump dan memantau secara eksternal untuk file-file itu:
java .... -XX:+HeapDumpOnOutOfMemoryError "-XX:OnOutOfMemoryError=kill %p"
Setelah bereksperimen dengan ini selama beberapa waktu, inilah solusi yang berhasil bagi kami:
- Dalam JVM yang dihasilkan, tangkap
OutOfMemoryError
dan segera keluar, menandakan kondisi memori habis dengan kode keluar ke JVM pengontrol. - Dalam JVM yang dihasilkan, periksa secara berkala jumlah memori yang digunakan dari
Runtime
saat ini . Ketika jumlah memori yang digunakan mendekati kritis, buat file flag yang menandakan kondisi kehabisan memori ke pengontrol JVM. Jika kami pulih dari kondisi ini dan keluar secara normal, hapus file tersebut sebelum kami keluar. - Setelah JVM pengontrol bergabung dengan JVM bercabang, ia memeriksa kode keluar yang dihasilkan pada langkah (1) dan file flag yang dihasilkan pada langkah (2). Selain itu, memeriksa apakah file
hs_err_pidXXX.log
ada dan berisi baris "Kesalahan Memori Habis". (File ini dihasilkan oleh java jika terjadi crash.)
Hanya setelah menerapkan semua pemeriksaan tersebut, kami dapat menangani semua kasus di mana JVM bercabang kehabisan memori. Kami percaya bahwa sejak saat itu, kami tidak melewatkan kasus di mana hal ini terjadi.
Bendera java -XX:OnOutOfMemoryError
tidak digunakan karena masalah fork, dan -XX:+HeapDumpOnOutOfMemoryError
tidak digunakan karena heap dump lebih dari yang kami butuhkan.
Solusinya tentu saja bukan potongan kode paling elegan yang pernah ditulis, tetapi berhasil untuk kami.