Global Exception Handler — boshqarilmagan istisnolarni markazlashtirilgan holda ushlash mexanizmi bo'lib, mobil ilovaning avariya bilan tugashini oldini oladi. Apple Developer, 2024 ma'lumotlariga ko'ra, istisnolarni to'g'ri boshqarish crash tushishlar sonini 40–60% kamaytiradi va foydalanuvchi tajribasini yaxshilaydi. Bunday handlersiz, fon oqimidagi har qanday boshqarilmagan istisno darhol ilovaning yopilishiga olib keladi.
Asosiy fikrlar
Global Exception Handler — bu ilovaning alohida funksiyalari yoki modullari darajasida boshqarilmagan istisnolarni ushlash uchun markazlashtirilgan mexanizm. Mobil ishlanma kontekstida bunday handler jarayonning avariya bilan tugashidan oldin so'nggi mudofaa chizig'i bo'lib xizmat qiladi.
iOS va Android global handler o'rnatish uchun o'rnatilgan API-larni taqdim etadi. Apple Objective-C muhiti uchun NSSetUncaughtExceptionHandler dan foydalanadi, Google esa Java/Kotlin da Thread.setDefaultUncaughtExceptionHandler ni taklif qiladi. Ikkala mexanizm ham ilovaning barcha oqimlarida try-catch konstruksiyalari tomonidan ushlanmagan istisnolarni tutadi.
Crashlytics (Google, 2024) ma'lumotlariga ko'ra, crash-larning taxminan 25% fon oqimlaridagi boshqarilmagan istisnolar tufayli yuz beradi — bu Global Exception Handler ayniqsa muhim bo'lgan sohadir. Dasturchilar ko'pincha UI oqimiga e'tibor qaratadilar, asinxron operatsiyalarni unutadilar.
Global handlerdan foydalanish mahalliy xato boshqaruvini almashtirmaydi, balki uni to'ldiradi. Asosiy vazifa — istisno momentida ilova holati haqida maksimal ma'lumotni saqlash va ishni to'g'ri yakunlashdir.
Ishlash mexanizmi — Global Exception Handler operatsion tizim signallari yoki bajarilish vaqti istisnolarini ushlashga asoslangan. Kod hech qanday try-catch bloki tomonidan ushlanmagan istisno tashlaganda, boshqaruv oldindan o'rnatilgan handler ga uzatiladi.
iOS platformasida handler NSSetUncaughtExceptionHandler orqali ro'yxatdan o'tadi va to'liq stack trace bilan NSException obyektini oladi. Android da Thread.setDefaultUncaughtExceptionHandler ishlatiladi, u Thread va Throwable ni qabul qiladi — bu istisno turiga, xabarga va chaqiruv stackiga kirish imkonini beradi.
Crash ma'lumoti olingandan so'ng, handler uchta majburiy harakatni bajaradi: mahalliy saqlashga log yozish, Crashlytics yoki Sentry ga hisobot yuborish va ilovani to'g'ri yakunlash. Apple WWDC 2023 ma'lumotlariga ko'ra, handlerning ishlash vaqti 5 soniya bilan cheklangan — bundan keyin tizim jarayonni majburiy ravishda tugatadi.
iOS 13 dan boshlab Swift ilovalari uchun Signals API paydo bo'ldi, u nafaqat istisnolarni, balki operatsion tizim signallarini — SIGABRT, SIGSEGV va SIGBUS ni ham qayta ishlaydi, handlerning qamrov zonasini past darajadagi xotira xatolarigacha kengaytiradi.
Tatbiq — iOS da global handler o'rnatish NSSetUncaughtExceptionHandler orqali C funksiyasini sozlashni talab qiladi. Handler boshqarilmagan istisno momentida sinxron ravishda chaqiriladi va to'liq xato kontekstini oladi.
void handleUncaughtException(NSException exception) {
NSDictionary userInfo = [exception userInfo];
NSArray stackTrace = [exception callStackSymbols];
NSString reason = [exception reason];
// Crash log-ni mahalliy faylga saqlaymiz
NSString logPath = [NSSearchPathForDirectoriesInDomains(
NSDocumentDirectory, NSUserDomainMask, YES) firstObject];
[exceptionLog writeToFile:logPath atomically:YES];
}
int main(int argc, char argv[]) {
NSSetUncaughtExceptionHandler(&handleUncaughtException);
return UIApplicationMain(argc, argv, nil, nil);
}
iOS tatbiqining muhim xususiyati: handler faqat Objective-C istisnolarini tutadi. Throw-catch mexanizmidan foydalanadigan Swift xatolari bu handler ga tushmaydi — ular uchun Swift Error Handling orqali alohida qayta ishlash talab qilinadi. iOS 14 dan boshlab Apple maksimal qamrov uchun NSSetUncaughtExceptionHandler ni Signals API bilan birlashtirishni tavsiya qiladi.
Apple Technical Note TN2151 ga ko'ra, handler chaqirilgandan so'ng, ilova 5 soniya ichida tugashi kerak. Handlerdan qaytgandan keyin bajarishni davom ettirishga urinish noaniq xatti-harakatga va qayta crash ga olib keladi.
Android Thread.setDefaultUncaughtExceptionHandler orqali yanada moslashuvchan global istisno boshqarish mexanizmini taqdim etadi. Handler istisno yuz bergan oqimga havolani va Throwable obyektining o'zini oladi.
class GlobalExceptionHandler : Thread.UncaughtExceptionHandler {
override fun uncaughtException(thread: Thread, throwable: Throwable) {
// Crash log-ni faylga saqlaymiz
val stackTrace = throwable.stackTraceToString()
val crashLog = "CRASH: ${thread.name}\n${stackTrace}"
val file = File(context.cacheDir, "crash_log.txt")
file.writeText(crashLog)
// Crashlytics ga yuboramiz
FirebaseCrashlytics.getInstance()
.recordException(throwable)
// Jarayonni tugatamiz
android.os.Process.killProcess(
android.os.Process.myPid()
)
}
}
// Application.onCreate da o'rnatish
class App : Application() {
override fun onCreate() {
super.onCreate()
Thread.setDefaultUncaughtExceptionHandler(
GlobalExceptionHandler()
)
}
}
Android tatbiqining asosiy farqi: har bir oqimning o'z handleri bor va setDefaultUncaughtExceptionHandler individual handler o'rnatilmagan barcha oqimlar uchun handler o'rnatadi. Bu global qamrovni ta'minlaydi — UI oqimidan tortib fon AsyncTask va korutinlargacha.
Android 12+ da cheklov paydo bo'ldi: uncaughtException chaqirilgandan so'ng, ilova 100 millisoniya ichida tugashi kerak. Agar handler uzoq davom etadigan operatsiyalarni bajarsa, tizim log yozilishi tugashidan oldin jarayonni o'ldirishi mumkin. Crash hisobotini yuborish uchun fon xizmatidan foydalanish tavsiya etiladi.
Birinchi qoida — boshqarilmagan istisnodan keyin ilova ishini tiklashga urinmang. Crash dan keyin ilova holati noaniq va ishni davom ettirish foydalanuvchi ma'lumotlarining buzilishiga olib kelishi mumkin.
Vaqt cheklovi — Global Exception Handler ning asosiy texnik cheklovidir. iOS da bu 5 soniya, Android da — 100 millisoniya. Handler ichida faqat minimal ma'lumotlar to'plamini saqlashga ruxsat beriladi: istisno turi, chaqiruv stacki va bir nechta asosiy o'zgaruvchilarning holati.
Tarmoq so'rovlarini yuborish, ma'lumotlar bazasiga yozish va murakkab serializatsiya kechiktirilgan mexanizmga o'tkazilishi kerak — masalan, logni faylga saqlash va uni ilovaning keyingi ishga tushirilishida yuborish.
Crash-reporting xizmatlari — Firebase Crashlytics, Sentry, Bugsnag — o'zlari global handler o'rnatadilar. Agar dasturchi o'z handlerini ularning ustiga o'rnatsa, o'z harakatlaridan so'ng boshqaruvni crash-reporting tizimiga topshirish kerak. Android da handler kompozitsiyasi ishlatiladi: o'z mantiqini bajarish, so'ngra oldingi handler ni chaqirish.
Firebase Crashlytics uchun umuman o'z Thread.setDefaultUncaughtExceptionHandler ni o'rnatmaslik tavsiya etiladi — Crashlytics SDK buni avtomatik ravishda ishga tushirishda amalga oshiradi.
Foydalanuvchi konteksti — standart chaqiruv stackidan tashqari, ilova versiyasini, OT versiyasini, bo'sh xotira miqdorini va crash gacha bo'lgan ish vaqtini loglash foydalidir. Bu ma'lumotlar muammoni qayta ishlab chiqarish va bartaraf etish uchun juda muhimdir.
iOS da NSSetUncaughtExceptionHandler nafaqat yozish uchun, balki ma'lumotlarni NSUserDefaults da synchronize bayrog'i bilan vaqtincha saqlash uchun ham ishlatilishi mumkin — bu jarayon darhol tugasa ham ma'lumotlarning saqlanishini kafolatlaydi.
Majburiy sinov — Global Exception Handler CI/CD ning har bir bosqichida sinovdan o'tkazilishi kerak. iOS da sinov istisnosi @throw NSException orqali, Android da esa throw RuntimeException() orqali boshlanishi mumkin. Handler chaqirilgani, log saqlangani va ilova to'g'ri tugaganligi tekshiriladi.
Google I/O 2023 ma'lumotlariga ko'ra, ishlab chiqarishdagi crash larning 30% dan ortig'i dasturchi sinovdan o'tkazmagan qurilmalarda sodir bo'ladi — turli Android versiyalari, maxsus proshivkalar, cheklangan xotira.
Birinchi va eng keng tarqalgan xato — istisno qayta ishlangandan so'ng ilova ishini davom ettirishga urinish. uncaughtException chaqirilgandan so'ng, ilova beqaror holatda bo'ladi va har qanday keyingi operatsiyalar xatolar kaskadiga va ma'lumotlarning buzilishiga olib kelishi mumkin.
Ikkinchi xato — handler ichida uzoq muddatli operatsiyalarni bajarish. Tarmoq so'rovlari, katta fayllarni yozish yoki murakkab hisob-kitoblar jarayonning majburiy tugatilishidan oldin tugashga ulgurmaydi. Apple Technical Q&A QA1468 ga ko'ra, handler ichida HTTP so'rovini yuborishga urinish yo'qotilgan crash hisobotlarining asosiy sababidir.
Uchinchi xato — fon oqimlarini e'tiborsiz qoldirish. Faqat asosiy oqim uchun o'rnatilgan Global Exception Handler korutinlar, DispatchQueue, AsyncTask yoki RxJava dagi crash lardan himoya qilmaydi. Android da har bir oqim o'z handleriga ega bo'lishi kerak — setDefaultUncaughtExceptionHandler bu muammoni faqat individual handleri bo'lmagan oqimlar uchun hal qiladi.
To'rtinchi xato — OT signallari uchun fallback ning yo'qligi. iOS da NSSetUncaughtExceptionHandler SIGABRT, SIGSEGV va SIGBUS ni tutmaydi. Bu signallar uchun sigaction API orqali alohida handlerlarni o'rnatish talab qilinadi. Dasturchilar bu haqda faqat ilova hech qanday crash hisobotisiz qulaganida bilib oladilar.
Beshinchi xato — maxfiy ma'lumotlarni loglash. Crash log ga elektron pochtalar, avtorizatsiya tokenlari yoki foydalanuvchilarning shaxsiy ma'lumotlari tushadi. Bu GDPR va Apple App Store Review Guidelines ni buzadi. Uzatiladigan ma'lumotlarni har doim regex yoki ruxsat etilgan maydonlarning whitelist ro'yxati orqali filtrlash kerak.
Tez-tez so'raladigan savollar
Yo'q — Global Exception Handler chaqirilgandan so'ng ilova holati noaniq. Ishni davom ettirishga har qanday urinish ma'lumotlarning buzilishiga olib kelishi mumkin. Yagona to'g'ri harakat — crash log ni saqlash va jarayonni tugatish.
Hammasini emas — iOS da NSSetUncaughtExceptionHandler faqat Objective-C istisnolarini tutadi. Swift xatolari va OT signallari (SIGSEGV, SIGABRT) alohida handlerlarni talab qiladi. Android da Thread.setDefaultUncaughtExceptionHandler barcha RuntimeException larni tutadi, lekin JNI orqali native kod xatolarini tutmaydi.
O'z handleringizni o'rnatishdan oldin Thread.getDefaultUncaughtExceptionHandler() orqali oldingi handler ga havolani saqlang. O'z handleringizning oxirida previousHandler.uncaughtException(thread, throwable) ni chaqiring — bu Crashlytics yoki Sentry o'z ma'lumotlarini olishini kafolatlaydi.
Native kod uchun sigaction() orqali signallarni qayta ishlash talab qilinadi — SIGSEGV, SIGABRT, SIGBUS. Android da Google Breakpad yoki Crashpad dan foydalanish mumkin. iOS 13 dan boshlab mach-istisnolarini qayta ishlash uchun Signals API mavjud.
Yo'q — handler ni o'rnatish faqat istisno momentida ta'sir qiladi. Oddiy ilova ishida overhead mavjud emas. Yagona xavf — agar handler Activity yoki Context ga havolani saqlab, ularning axlat yig'uvchi tomonidan tozalanishiga to'sqinlik qilsa, xotira oqishi yuz berishi mumkin.
Xulosa
Biz kalit topshirig'i bilan mobil ilovani ishlab chiqamiz
IT Sectr 2017-yildan beri startaplar va korxonalar uchun iOS va Android ilovalarini yaratadi. Biz sizga maslahat beramiz va eng yaxshi yechimni taklif qilamiz.