DeadObjectException neden ortaya çıkar ve bununla ne yapılmalı
DeadObjectException, bir istemci süreci veya servisi zaten sonlandırılmış olan uzak bir nesnenin (IBinder) yöntemlerini çağırdığında meydana gelir; bunu düzeltmek için isBinderAlive/pingBinder kontrolü, onServiceDisconnected öğesinin doğru şekilde işlenmesi, yaşam döngüsüne duyarlı bileşenlere geçiş ve yedek mantık ekleme (yeniden bağlanma veya hata toleranslı yol) gereklidir.
DeadObjectException nedir ve tipik senaryolar
DeadObjectException, RemoteException'ın bir alt sınıfıdır: Uzak Binder'ın artık çalışmadığına dair bir sinyal. Sık görülen senaryolar:
- Bağlı Servis sistem tarafından (düşük bellek nedeniyle) sonlandırıldı ve istemci eski IBinder'ı tutmaya devam etti.
- Activity/Fragment'in onDestroy() çağrısından sonra yöntemlerin çağrılması.
- Alıcı tarafın çalışmayı sonlandırdığı AIDL/Messenger üzerinden IPC.
- Bellek sızıntıları: Statik alanlar veya Handler, IBinder referanslarını tutuyor.
Sorunu nasıl teşhis edilir
- Logcat: DeadObjectException filtresi — yığın izini ve çağrı noktasını bulacaksınız.
- Binder sızıntılarını tespit etmek için debug modunda StrictMode'u etkinleştirin:
if (BuildConfig.DEBUG) {
StrictMode.setThreadPolicy(
StrictMode.ThreadPolicy.Builder()
.detectAll()
.penaltyLog()
.build()
)
}
- ServiceConnection içindeki onServiceDisconnected öğesini kontrol edin — genellikle referansların serbest bırakılması burada unutulur.
- Süreç öldürmeyi simüle etme: adb shell am kill
veya düşük bellekli testler.
Yığında, servisin sistem tarafından yok edilmesinden hemen sonra istemci tarafında bir çağrı görülüyorsa — IBinder'ın kaydedildiği ve kontrol olmadan yöntemin çağrıldığı yeri arayın.
Pratik çözüm yöntemleri
- ServiceConnection içinde işleme:
private var binder: IMyAidlInterface? = null
private val connection = object : ServiceConnection {
override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
binder = IMyAidlInterface.Stub.asInterface(service)
}
override fun onServiceDisconnected(name: ComponentName?) {
// servis öldü — referansları temizle ve istekleri durdur
binder = null
}
}
- Çağırmadan önce durumu kontrol etme:
val b = (binder as? IBinder)
if (b?.isBinderAlive == true) {
b.pingBinder()
binder?.someMethod()
} else {
// yeniden bağlanma veya kullanıcıya hata gösterme
}
- Yaşam döngüsüne duyarlı yaklaşımlar:
- Doğrudan Context referansları tutmamak için arka plan mantığında ViewModel + LiveData/StateFlow kullanın.
- onStop/onDestroy sırasında servislerden abonelikten çıkın ve kaynakları LifecycleObserver veya ProcessLifecycleOwner aracılığıyla serbest bırakın.
- IPC seçimi:
- Basit görevler için karmaşık AIDL yerine Messenger veya PendingIntent kullanın.
- Arka plan görevleri için uzun ömürlü servisler yerine WorkManager kullanın.
IBinder veya Context'i statik alanlarda asla saklamayın — bu, sızıntıların ve ardından gelen DeadObjectException'ların sık görülen bir nedenidir.
Yaklaşımların kısa karşılaştırması
| Yaklaşım | Zorluk | Ne zaman uygun |
|---|---|---|
| ServiceConnection + onServiceDisconnected | Düşük | Bağlı servisler |
| pingBinder/isBinderAlive | Orta | Servise sık çağrılar |
| LifecycleObserver / ViewModel | Düşük | Kullanıcı arayüzü ile ilgili bileşenler |
| AIDL yerine Messenger | Yüksek | Basitleştirilmiş IPC, karmaşık AIDL yokluğu |
Sık yapılan hatalar
- onServiceDisconnected'i görmezden gelmek ve çağrıları sürdürmek.
- IBinder'ı statik veya uzun ömürlü nesnelerde saklamak.
- Activity'nin onDestroy() sonrasında servise erişim denemeleri.
- Servis kullanılamadığında yedek mantığın bulunmaması.
SSS
-
DeadObjectException try/catch ile yakalanmalı mı?
Evet, kritik noktalarda RemoteException/DeadObjectException yakalayın ve yedek işlemi gerçekleştirin (yeniden bağlanma veya kademeli bozulma). -
WorkManager'a geçiş yardımcı olur mu?
Arka plan görevleri için evet. WorkManager, servislerin zorla sonlandırılmasıyla ilgili birçok sorunu ortadan kaldırır. -
Hata hızlıca nasıl çoğaltılır?
adb shell am killveya düşük bellekli cihazda test etme.
Düzeltmelerden sonra hata devam ediyorsa — yığın izini ekleyin ve senaryoyu açıklayın (bağlı servis, AIDL, Activity yaşam döngüsü) — nokta atışı yardımcı olabilirim.