Yanıtlar:
Genellikle, asla.
Ancak, bazen belirli hataları yakalamanız gerekir.
Framework-ish kod yazıyorsanız (3. taraf sınıfları yüklüyorsanız), yakalamak akıllıca olabilir LinkageError
(sınıf bulunamadı, tatmin edici olmayan bağlantı, uyumsuz sınıf değişikliği).
Ayrıca alt sınıfları atan bazı aptal üçüncü taraf kodlar da gördüm Error
, bu yüzden bunları da halletmeniz gerekecek.
Bu arada, iyileşmenin mümkün olmadığından emin değilim OutOfMemoryError
.
Asla. Uygulamanın sonraki kod satırını çalıştırabileceğinden asla emin olamazsınız. Eğer bir alırsanız OutOfMemoryError
, her şeyi güvenilir bir şekilde yapabileceğinizi garanti edemezsiniz . RuntimeException'ı yakalayın ve İstisnaları işaretleyin, ancak Hatalar'ı asla kontrol etmedi.
boolean assertionsEnabled = false; assert assertionsEnabled = true;
Genellikle, her zaman yakalayıp java.lang.Error
bir günlüğe yazmalı veya kullanıcıya göstermelisiniz. Destek olarak çalışıyorum ve her gün programcıların bir programda ne olduğunu söyleyemediklerini görüyorum.
Bir daemon iş parçacığınız varsa, sonlandırılmasını önlemelisiniz. Diğer durumlarda uygulamanız düzgün çalışacaktır.
Sadece java.lang.Error
en yüksek seviyede yakalamalısın .
Hataların listesine bakarsanız, çoğunun ele alınabileceğini göreceksiniz. Örneğin ZipError
, bozuk zip dosyalarını okurken bir meydana gelir.
En yaygın hatalar OutOfMemoryError
ve NoClassDefFoundError
çoğu durumda her ikisi de çalışma zamanı sorunlarıdır.
Örneğin:
int length = Integer.parseInt(xyz);
byte[] buffer = new byte[length];
bir üretebilir, OutOfMemoryError
ancak bu bir çalışma zamanı problemidir ve programınızı sonlandırmanız için bir neden yoktur.
NoClassDefFoundError
çoğunlukla bir kitaplık yoksa veya başka bir Java sürümüyle çalışıyorsanız oluşur. Programınızın isteğe bağlı bir parçasıysa, programınızı sonlandırmamalısınız.
Throwable
En üst seviyede yakalamanın ve yardımcı bir hata mesajı üretmenin neden iyi bir fikir olduğuna dair daha birçok örnek verebilirim .
OutOfMemoryError
bir çalışma zamanı hatası değildir, uygulamanın bundan kurtulabileceğinin garantisi yoktur. Şanslıysanız, OOM alabilirsiniz, new byte[largeNumber]
ancak bu tahsis OOM'ye neden olmak için yeterli değilse, sonraki satırda veya sonraki iş parçacığında tetiklenebilir. Bu çalışma zamanı sorunudur, çünkü length
güvenilir olmayan bir girdi ise , çağrı yapmadan önce doğrulanması gerekir new byte[]
.
NoClassDefFoundError
oluşabilir yerde derlenmiş java kodu bir sınıf bulamadıkları zaman o çağrılır olarak. JDK'nız yanlış yapılandırılmışsa, java.util.*
sınıfı kullanmaya çalışmaktan tetiklenebilir ve ona karşı programlamak pratik olarak imkansızdır. İsteğe bağlı olarak bir bağımlılık ekliyorsanız, ClassLoader
var olup olmadığını kontrol etmek için kullanmalısınız , bu da fırlatır ClassNotFoundException
.
ZipError
sınıfları içeren jar dosyasının bozuk bir zip dosyası olduğunu belirtir. Bu oldukça ciddi bir sorundur ve bu noktada çalıştırılan herhangi bir koda güvenemezsiniz ve ondan "kurtarmaya" çalışmak sorumsuzca bir şey olur.
java.lang.Error
veya java.lang.Throwable
en üst düzeyde yapmak ve onunla bir şeyler yapmaya çalışmak faydalı olabilir - diyelim ki bir hata mesajı kaydedin. Ancak bu noktada bunun yerine getirileceğine dair bir garanti yok. JVM'niz String
OOM yapıyorsa, günlüğe kaydetmeye çalışmak başka bir OOM'yi tetikleyen daha fazla s tahsis edebilir .
Çok iş parçacıklı bir ortamda, çoğu zaman onu yakalamak istersiniz! Yakaladığınızda, günlüğe kaydedin ve tüm uygulamayı sonlandırın! Bunu yapmazsanız, önemli bir kısmını yapan bazı iş parçacıkları ölür ve uygulamanın geri kalanı her şeyin normal olduğunu düşünür. Bunun dışında birçok istenmeyen durum ortaya çıkabilir. En küçük sorunlardan biri, bir iş parçacığının çalışmaması nedeniyle diğer iş parçacıkları bazı istisnalar atmaya başlarsa, sorunun kökenini kolayca bulamayacağınızdır.
Örneğin, genellikle döngü şöyle olmalıdır:
try {
while (shouldRun()) {
doSomething();
}
}
catch (Throwable t) {
log(t);
stop();
System.exit(1);
}
Bazı durumlarda bile, farklı Hataları farklı şekilde ele almak isteyebilirsiniz, örneğin, OutOfMemoryError'da uygulamayı düzenli olarak kapatabilirsiniz (hatta bir miktar hafızayı boşaltabilir ve devam edebilirsiniz), bazılarında ise yapabileceğiniz pek bir şey yoktur.
OutOfMemoryError
ve devam etmek akıllıca değildir , çünkü programınız o zaman tanımlanmamış bir durumdadır .
Bir Error
genellikle yakalanmış olmamalı o kadar, hiçbir zaman ortaya anormal bir duruma işaret eder .
Error
Sınıf için Java API Spesifikasyonundan :
An
Error
,Throwable
makul bir uygulamanın yakalamaya çalışmaması gereken ciddi sorunları gösteren bir alt sınıfıdır . Bu tür hataların çoğu anormal durumlardır. [...]Bir yöntemin, yöntemin yürütülmesi sırasında atılan ancak yakalanmayan herhangi bir Error alt sınıfını kendi throws cümlesinde bildirmesi gerekmez, çünkü bu hatalar asla oluşmaması gereken anormal koşullardır.
Spesifikasyonda belirtildiği gibi, bir Error
yalnızca Şansların olduğu durumlarda atılır, bir Error
meydana geldiğinde uygulamanın yapabileceği çok az şey vardır ve bazı durumlarda Java Sanal Makinesi kararsız bir durumda olabilir (örneğin VirtualMachineError
)
Error
Bir alt sınıfı olmasına rağmen , bir cümle Throwable
tarafından yakalanabileceği anlamına gelir try-catch
, ancak Error
JVM tarafından bir atıldığında uygulama anormal bir durumda olacağından muhtemelen gerçekten gerekli değildir .
Bölümde bu konuda kısa bir bölüm de var 11.5 İstisna Hiyerarşi içinde Java Dili Şartname, 2. Baskı .
Ve bir Hata alırsanız , onu yeniden atmanız gereken birkaç durum daha vardır . Örneğin, ThreadDeath asla yakalanmamalıdır, büyük bir soruna neden olabilir, eğer onu kapalı bir ortamda yakalarsanız (örneğin bir uygulama sunucusu):
Bir uygulama, bu sınıfın örneklerini ancak zaman uyumsuz olarak sonlandırıldıktan sonra temizlemesi gerekiyorsa yakalamalıdır. ThreadDeath bir yöntem tarafından yakalanırsa, iş parçacığının gerçekten ölmesi için yeniden atılması önemlidir.
Error
s.
Çok çok nadiren.
Bunu sadece çok özel bilinen bir vaka için yaptım. Örneğin, iki bağımsız ClassLoader aynı DLL dosyasını yüklüyse java.lang.UnsatisfiedLinkError atılabilir . (JAR'ı paylaşılan bir sınıf yükleyiciye taşımam gerektiğini kabul ediyorum)
Ancak en yaygın durum, kullanıcı şikayet etmeye geldiğinde ne olduğunu öğrenmek için oturum açmanız gerektiğidir. Sessizce ölmek yerine kullanıcıya bir mesaj veya açılır pencere istiyorsun.
C / C ++ programcıları bile, bir hatayı ortaya çıkarırlar ve çıkmadan önce insanların anlamadıkları bir şeyi söylerler (örneğin, hafıza hatası).
Bir Android uygulamasında bir java.lang.VerifyError yakalıyorum . Kullandığım bir kitaplık, işletim sisteminin eski sürümüne sahip cihazlarda çalışmaz ve kitaplık kodu böyle bir hata verir. İşletim zamanında işletim sistemi sürümünü kontrol ederek hatayı elbette önleyebilirim, ancak:
İdeal olarak hataları işlememeli / yakalamamalıyız. Ancak çerçevenin veya uygulamanın gerekliliğine bağlı olarak yapmamız gereken durumlar olabilir. Daha fazla Bellek tüketen DOM Ayrıştırıcıyı uygulayan bir XML Ayrıştırıcı arka plan programım olduğunu varsayalım . Ayrıştırıcı iş parçacığı gibi bir gereksinim varsa OutOfMemoryError aldığında ölmemeli , bunun yerine onu ele almalı ve uygulama / çerçeve yöneticisine bir mesaj / posta göndermelidir.
JVM artık beklendiği gibi çalışmadığında veya eşiğinde olduğunda bir Hata var. Bir hata yakalarsanız, catch bloğunun çalışacağının ve sonuna kadar çalışacağının garantisi yoktur.
Aynı zamanda çalışan bilgisayara, mevcut bellek durumuna da bağlı olacaktır, bu nedenle test etmenin, denemenin ve elinizden gelenin en iyisini yapmanın bir yolu yoktur. Sadece kötü bir sonuca sahip olacaksınız.
Ayrıca kodunuzun okunabilirliğini de düşüreceksiniz.