OOME yakalanabilir, ancak JVM'nin yakalamaya ulaşıldığında bazı nesneleri toplayıp toplayıp toplayamadığına ve o zamana kadar kaç yığın bellek kaldığına bağlı olarak genellikle yararsız olacaktır.
Örnek: JVM'mde bu program tamamlanana kadar çalışıyor:
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");
}
}
Ancak, yakalamaya sadece tek bir satır eklemek, size neden bahsettiğimi gösterecektir:
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");
}
}
İlk program sorunsuz çalışır çünkü yakalamaya ulaşıldığında, JVM listenin artık kullanılmayacağını algılar (Bu algılama aynı zamanda derleme zamanında yapılan bir optimizasyon olabilir). Böylece, yazdırma ifadesine ulaştığımızda, yığın belleği neredeyse tamamen serbest kaldı, bu nedenle artık devam etmek için geniş bir manevra marjına sahibiz. Bu en iyi durumdur.
Ancak kod, liste gibi ll
OOME yakalandıktan sonra kullanılacak şekilde düzenlenirse , JVM kodu toplayamaz. Bu ikinci parçada olur. Yeni bir Long yaratımıyla tetiklenen OOME yakalandı, ancak yakında yeni bir Nesne ( System.out,println
satırda bir String ) oluşturuyoruz ve yığın neredeyse dolu, bu yüzden yeni bir OOME atılıyor. Bu en kötü durum senaryosu: yeni bir nesne yaratmaya çalıştık, başarısız olduk, OOME'yi yakaladık, evet, ama şimdi yeni yığın belleği gerektiren ilk talimat (örneğin: yeni bir nesne oluşturma) yeni bir OOME atacak. Bir düşünün, bu noktada çok az hafıza kaldığında başka ne yapabiliriz? Muhtemelen çıkıyorum. Dolayısıyla işe yaramaz.
JVM'nin kaynakları toplamamasının sebeplerinden biri gerçekten korkutucudur: diğer iş parçacıklarıyla paylaşılan bir kaynak da ondan yararlanır. Beyni olan herkes, herhangi bir tür deneysel olmayan uygulamaya yerleştirildiğinde OOME'u yakalamanın ne kadar tehlikeli olabileceğini görebilir.
Windows x86 32bits JVM (JRE6) kullanıyorum. Her Java uygulaması için varsayılan bellek 64MB'dir.