Global Exception Handler: lényeg, működési elv és megvalósítás a projektekben

Szerző: IT Sectr Megjelenés: 2026-05-27 Olvasási idő: 8 perc

Global Exception Handler — a kezeletlen kivételek központosított elfogásának mechanizmusa, amely megakadályozza a mobilalkalmazás váratlan leállását. A Apple Developer, 2024 adatai szerint a kivételek helyes kezelése 40–60%-kal csökkenti a crash-ek számát és javítja a felhasználói élményt. Ilyen kezelő nélkül bármely kezeletlen kivétel egy háttérszálon az alkalmazás azonnali bezárásához vezet.

Főbb pontok

  • Global Exception Handler — az összes kezeletlen kivétel gyűjtőpontja az alkalmazásban, megelőzi a crash-eket
  • iOS NSSetUncaughtExceptionHandler — C függvény az Objective-C kivételek elfogására az Apple platformon
  • Android Thread.setDefaultUncaughtExceptionHandler — a platform beépített mechanizmusa a globális kivételfogáshoz
  • Naplózás lezárás előtt — a kezelő fő feladata: a crash információ mentése a folyamat befejezése előtt
  • Graceful degradation — a kezelő lehetővé teszi a helyes hibaüzenet megjelenítését a váratlan leállás helyett

Mi az a Global Exception Handler?

Global Exception Handler — egy központosított mechanizmus azon kivételek elfogására, amelyeket nem kezeltek az alkalmazás egyes függvényeinek vagy moduljainak szintjén. A mobilfejlesztés kontextusában az ilyen kezelő az utolsó védelmi vonalként szolgál a folyamat kényszerített megszakítása előtt.

Az iOS és Android beépített API-kat biztosítanak a globális kezelő beállításához. Az Apple az NSSetUncaughtExceptionHandler-t használja az Objective-C környezethez, a Google pedig a Thread.setDefaultUncaughtExceptionHandler-t kínálja Java/Kotlin nyelven. Mindkét mechanizmus elkapja azokat a kivételeket, amelyeket a try-catch szerkezetek nem fogtak el az alkalmazás összes szálán.

A Crashlytics (Google, 2024) adatai szerint a crash-ek körülbelül 25%-a kezeletlen kivételek miatt következik be háttérszálakon — ez az a terület, ahol a Global Exception Handler különösen kritikus. A fejlesztők gyakran az UI szálra összpontosítanak, megfeledkezve az aszinkron műveletekről.

A globális kezelő használata nem helyettesíti a helyi hibakezelést, hanem kiegészíti azt. A fő feladat — maximális információ mentése az alkalmazás állapotáról a kivétel pillanatában és a munka helyes befejezése.

Hogyan működik a globális kivételkezelő

Működési mechanizmus — a Global Exception Handler az operációs rendszer jeleinek vagy futásidejű kivételek elfogásán alapul. Amikor a kód olyan kivételt dob, amelyet egyetlen try-catch blokk sem fogott el, a vezérlés átadódik az előre beállított kezelőnek.

Az iOS platformon a kezelő az NSSetUncaughtExceptionHandler-en keresztül regisztrálódik, és egy NSException objektumot kap teljes stack trace-szel. Androidon a Thread.setDefaultUncaughtExceptionHandler-t használják, amely Thread-et és Throwable-t fogad — ez hozzáférést biztosít a kivétel típusához, üzenethez és hívási veremhez.

A crash adatok fogadása után a kezelő három kötelező műveletet hajt végre: napló írása a helyi tárolóba, jelentés küldése a Crashlytics vagy Sentry részére, és az alkalmazás helyes befejezése. Az Apple WWDC 2023 szerint a kezelő munkaideje 5 másodpercre korlátozódik — ezt követően a rendszer kényszerítve befejezi a folyamatot.

Az iOS 13-tól kezdve a Swift alkalmazásokhoz megjelent a Signals API, amely nemcsak a kivételeket, hanem az operációs rendszer jeleit is feldolgozza — SIGABRT, SIGSEGV és SIGBUS — ezzel kiterjesztve a kezelő lefedettségét az alacsony szintű memóriahibákra.

Global Exception Handler megvalósítása iOS-en

Megvalósítás — a globális kezelő iOS-en való beállításához C függvény beállítása szükséges az NSSetUncaughtExceptionHandler-en keresztül. A kezelő szinkron módon hívódik meg egy kezeletlen kivétel pillanatában, és megkapja a teljes hiba kontextust.

objective-c
void handleUncaughtException(NSException exception) {
    NSDictionary userInfo = [exception userInfo];
    NSArray stackTrace = [exception callStackSymbols];
    NSString reason = [exception reason];

    // Crash napló mentése helyi fájlba
    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);
}

Fontos jellemzője az iOS megvalósításnak: a kezelő csak Objective-C kivételeket fog el. A Swift hibák, amelyek a throw-catch mechanizmust használják, nem jutnak el ehhez a kezelőhöz — számukra külön feldolgozás szükséges a Swift Error Handling-en keresztül. iOS 14-től az Apple a NSSetUncaughtExceptionHandler és a Signals API kombinálását ajánlja a maximális lefedettség érdekében.

A Apple Technical Note TN2151 szerint a kezelő meghívása után az alkalmazásnak 5 másodpercen belül be kell fejeződnie. Bármilyen kísérlet a végrehajtás folytatására a kezelőből való visszatérés után meghatározatlan viselkedéshez és ismételt crash-hez vezet.

Global Exception Handler megvalósítása Androidon

Android rugalmasabb mechanizmust kínál a globális kivételkezeléshez a Thread.setDefaultUncaughtExceptionHandler-en keresztül. A kezelő megkapja a hivatkozást arra a szálra, amelyben a kivétel történt, és magát a Throwable objektumot.

kotlin
class GlobalExceptionHandler : Thread.UncaughtExceptionHandler {

    override fun uncaughtException(thread: Thread, throwable: Throwable) {
        // Crash napló mentése fájlba
        val stackTrace = throwable.stackTraceToString()
        val crashLog = "CRASH: ${thread.name}\n${stackTrace}"

        val file = File(context.cacheDir, "crash_log.txt")
        file.writeText(crashLog)

        // Küldés Crashlytics-be
        FirebaseCrashlytics.getInstance()
            .recordException(throwable)

        // Folyamat befejezése
        android.os.Process.killProcess(
            android.os.Process.myPid()
        )
    }
}

// Telepítés az Application.onCreate-ben
class App : Application() {
    override fun onCreate() {
        super.onCreate()
        Thread.setDefaultUncaughtExceptionHandler(
            GlobalExceptionHandler()
        )
    }
}

Fő különbség az Android megvalósításban: minden szálnak saját kezelője van, és a setDefaultUncaughtExceptionHandler azon szálak számára állít be kezelőt, amelyeknek nincs egyedi kezelőjük. Ez globális lefedettséget biztosít — az UI száltól a háttérbeli AsyncTask-ig és korutinokig.

Android 12+-tól kezdve korlátozás lépett életbe: az uncaughtException meghívása után az alkalmazásnak 100 ezredmásodpercen belül be kell fejeződnie. Ha a kezelő hosszú ideig tartó műveleteket hajt végre, a rendszer megölheti a folyamatot a naplózás befejezése előtt. Javasolt háttérszolgáltatás használata a crash jelentés küldéséhez.

Legjobb gyakorlatok a Global Exception Handler használatához

Első szabály — ne próbálja helyreállítani az alkalmazást egy kezeletlen kivétel után. Az alkalmazás állapota crash után meghatározatlan, és a munka folytatása a felhasználói adatok sérüléséhez vezethet.

A kezelő munkaidejének minimalizálása

Időkorlát — a Global Exception Handler fő technikai korlátozása. iOS-en ez 5 másodperc, Androidon — 100 ezredmásodperc. A kezelőn belül csak minimális adatkészlet mentése engedélyezett: a kivétel típusa, a hívási verem és néhány kulcsváltozó állapota.

A hálózati kérések küldését, adatbázisba írást és összetett szerializációt halasztott mechanizmusba kell áthelyezni — például a napló mentése fájlba, majd elküldése az alkalmazás következő indításakor.

Kombinálás crash-reporting rendszerekkel

Crash-reporting szolgáltatások — Firebase Crashlytics, Sentry, Bugsnag — maguk állítják be a globális kezelőt. Ha a fejlesztő saját kezelőt telepít föléjük, a saját műveletei után át kell adnia a vezérlést a crash-reporting rendszernek. Androidon kezelő kompozíciót használnak: saját logika végrehajtása, majd az előző kezelő meghívása.

A Firebase Crashlytics esetében ajánlott egyáltalán nem telepíteni egyéni Thread.setDefaultUncaughtExceptionHandler-t — a Crashlytics SDK ezt automatikusan elvégzi az inicializáláskor.

További információk naplózása

Felhasználói kontextus — a szokásos hívási vermen kívül érdemes naplózni az alkalmazás verzióját, az operációs rendszer verzióját, a szabad memória mennyiségét és a crash-ig eltelt munkaidőt. Ezek az adatok kritikus fontosságúak a probléma reprodukálásához és megoldásához.

iOS-en az NSSetUncaughtExceptionHandler nemcsak naplózáshoz használható, hanem adatok ideiglenes tárolására is az NSUserDefaults-ban synchronize jelzővel — ez garantálja az adatok megőrzését még a folyamat azonnali befejezése esetén is.

A kezelő tesztelése kiadás előtt

Kötelező tesztelés — a Global Exception Handler-t a CI/CD minden szakaszában tesztelni kell. iOS-en teszt kivétel indítható a @throw NSException segítségével, Androidon a throw RuntimeException() segítségével. Ellenőrizni kell, hogy a kezelő meghívódik, a napló elmentődik és az alkalmazás helyesen befejeződik.

A Google I/O 2023 szerint a termelésben előforduló crash-ek több mint 30%-a olyan eszközökön történik, amelyeket a fejlesztő nem tesztelt — különböző Android verziók, egyedi firmware, korlátozott memória.

Gyakori hibák a kezelő használatakor

Első és leggyakoribb hiba — az alkalmazás végrehajtásának folytatása a kivétel feldolgozása után. Az uncaughtException meghívása után az alkalmazás instabil állapotban van, és minden további művelet hibák kaszkádját és adatsérülést okozhat.

Második hiba — hosszú ideig tartó műveletek végrehajtása a kezelőn belül. Hálózati kérések, nagy fájlok írása vagy összetett számítások nem fejeződnek be a folyamat kényszerített befejezése előtt. Az Apple Technical Q&A QA1468 szerint a HTTP kérés küldésére tett kísérlet a kezelőn belül a vezető oka az elveszett crash jelentéseknek.

Harmadik hiba — a háttérszálak figyelmen kívül hagyása. A csak a főszálra beállított Global Exception Handler nem véd a crash-ektől a korutinokban, DispatchQueue-ban, AsyncTask-ben vagy RxJava-ban. Androidon minden szálnak saját kezelővel kell rendelkeznie — a setDefaultUncaughtExceptionHandler csak azon szálak esetében oldja meg ezt a problémát, amelyeknek nincs egyedi kezelőjük.

Negyedik hiba — az operációs rendszer jeleire vonatkozó tartalék megoldás hiánya. Az NSSetUncaughtExceptionHandler iOS-en nem fogja el a SIGABRT, SIGSEGV és SIGBUS jeleket. Ezekhez a jelekhez külön kezelők telepítése szükséges a sigaction API-n keresztül. A fejlesztők csak akkor szembesülnek ezzel, amikor az alkalmazás crash-el anélkül, hogy bármilyen crash jelentés készülne.

Ötödik hiba — bizalmas adatok naplózása. A crash naplóba e-mailek, hitelesítési tokenek vagy felhasználók személyes adatai kerülnek. Ez sérti a GDPR-t és az Apple App Store Review Guidelines-t. Mindig szűrje a továbbított adatokat regex vagy engedélyezett mezők whitelist listája segítségével.

Gyakran Ismételt Kérdések

Helyreállítható az alkalmazás egy globális kivétel után?

Nem — a Global Exception Handler meghívása után az alkalmazás állapota meghatározatlan. Bármilyen kísérlet a munka folytatására adatsérüléshez vezethet. Az egyetlen helyes művelet — a crash napló mentése és a folyamat befejezése.

Elfogja a Global Exception Handler az összes hibátípust?

Nem mindet — iOS-en az NSSetUncaughtExceptionHandler csak az Objective-C kivételeket fogja el. A Swift hibák és az operációs rendszer jelei (SIGSEGV, SIGABRT) külön kezelőket igényelnek. Androidon a Thread.setDefaultUncaughtExceptionHandler az összes RuntimeException-t elkapja, de a JNI-n keresztüli natív kódhibákat nem.

Hogyan adjam át a vezérlést a crash-reporting rendszernek a saját kezelőm után?

Mentse el a hivatkozást az előző kezelőre a Thread.getDefaultUncaughtExceptionHandler()-en keresztül a saját kezelő telepítése előtt. A kezelő végén hívja meg a previousHandler.uncaughtException(thread, throwable) függvényt — ez garantálja, hogy a Crashlytics vagy a Sentry megkapja az adatait.

Mi a teendő, ha a crash C/C++ natív kódban történt?

Natív kód esetén jelkezelés szükséges a sigaction()-on keresztül — SIGSEGV, SIGABRT, SIGBUS. Androidon használható a Google Breakpad vagy a Crashpad. iOS-en a 13-as verziótól elérhető a Signals API a mach kivételek kezeléséhez.

Befolyásolhatja a Global Exception Handler a teljesítményt?

Nem — a kezelő telepítése csak a kivétel pillanatában van hatással. Normál alkalmazás működés közben nincs többletterhelés. Az egyetlen kockázat a memóriaszivárgás, ha a kezelő hivatkozást tárol egy Activity-re vagy Context-re, megakadályozva azok szemétgyűjtését.

Összefoglalás

  • Global Exception Handler — az utolsó védelmi vonal crash előtt, kötelező minden termelési alkalmazásban
  • iOS NSSetUncaughtExceptionHandler elfogja az Objective-C kivételeket 5 másodperces feldolgozási korláttal
  • Android Thread.setDefaultUncaughtExceptionHandler minden olyan szál esetén működik, amelynek nincs saját kezelője
  • A kezelő munkaideje minimális legyen — adatok mentése és a folyamat befejezése helyreállítási kísérlet nélkül
  • Operációs rendszer jeleit (SIGSEGV, SIGABRT) a szabványos kezelők nem fogják el — sigaction API szükséges
  • Crash-reporting rendszereket kezelő kompozíción keresztül kell meghívni, átadva a vezérlést a saját logika után
  • A kezelő tesztelése CI/CD-ben — kötelező szakasz, amely megakadályozza a crash jelentések elvesztését a termelésben

Kulcsrakész mobilalkalmazást fejlesztünk

Az IT Sectr 2017 óta készít iOS és Android alkalmazásokat induló vállalkozásoknak és vállalkozásoknak. Tanácsot adunk, és a legjobb megoldást javasoljuk.

Projekt megbeszélése

Olvassa el is