OOME dapat ditangkap tetapi secara umum tidak akan berguna, tergantung pada apakah JVM dapat mengumpulkan sampah untuk mengumpulkan beberapa objek saat tangkapan tercapai, dan berapa banyak memori heap yang tersisa saat itu.
Contoh: di JVM saya, program ini berjalan sampai selesai:
import java.util.LinkedList;
import java.util.List;
public class OOMErrorTest {
public static void main(String[] args) {
List<Long> ll = new LinkedList<Long>();
try {
long l = 0;
while(true){
ll.add(new Long(l++));
}
} catch(OutOfMemoryError oome){
System.out.println("Error catched!!");
}
System.out.println("Test finished");
}
}
Namun, hanya menambahkan satu baris pada tangkapan akan menunjukkan kepada Anda apa yang saya bicarakan:
import java.util.LinkedList;
import java.util.List;
public class OOMErrorTest {
public static void main(String[] args) {
List<Long> ll = new LinkedList<Long>();
try {
long l = 0;
while(true){
ll.add(new Long(l++));
}
} catch(OutOfMemoryError oome){
System.out.println("Error catched!!");
System.out.println("size:" +ll.size());
}
System.out.println("Test finished");
}
}
Program pertama berjalan dengan baik karena ketika tangkapan tercapai, JVM mendeteksi bahwa daftar tersebut tidak akan digunakan lagi (Deteksi ini juga dapat berupa pengoptimalan yang dilakukan pada waktu kompilasi). Jadi ketika kami mencapai pernyataan cetak, memori heap telah dibebaskan hampir seluruhnya, jadi kami sekarang memiliki margin manuver yang lebar untuk melanjutkan. Ini kasus terbaik.
Namun, jika kode diatur seperti daftar ll
yang digunakan setelah OOME ditangkap, JVM tidak dapat mengumpulkannya. Ini terjadi di cuplikan kedua. OOME, yang dipicu oleh pembuatan Long baru, ditangkap, tetapi segera kami membuat Objek baru (String di System.out,println
baris), dan tumpukan hampir penuh, jadi OOME baru dilemparkan. Ini adalah skenario kasus terburuk: kami mencoba membuat objek baru, kami gagal, kami menangkap OOME, ya, tetapi sekarang instruksi pertama yang membutuhkan memori heap baru (misalnya: membuat objek baru) akan mengeluarkan OOME baru. Pikirkan tentang itu, apa lagi yang bisa kita lakukan pada saat ini dengan sedikit memori yang tersisa ?. Mungkin baru keluar. Karenanya yang tidak berguna.
Di antara alasan JVM tidak mengumpulkan sumber daya, satu hal yang sangat menakutkan: sumber daya bersama dengan utas lain juga memanfaatkannya. Siapa pun yang memiliki otak dapat melihat betapa berbahayanya menangkap OOME jika dimasukkan ke aplikasi non-eksperimental dalam bentuk apa pun.
Saya menggunakan Windows x86 32bits JVM (JRE6). Memori default untuk setiap aplikasi Java adalah 64MB.