Global Exception Handler: essens, arbetsprincip och implementering i projekt

Författare: IT Sectr Publicerad: 2026-05-27 Lästid: 8 min

Global Exception Handler — en centraliserad mekanism för att fånga ohanterade undantag som förhindrar att en mobilapplikation kraschar. Enligt Apple Developer, 2024 minskar korrekt undantagshantering antalet krascher med 40–60% och förbättrar användarupplevelsen. Utan en sådan hanterare leder varje ohanterat undantag i en bakgrundstråd till omedelbar avstängning av appen.

Huvudpunkter

  • Global Exception Handler — samlingspunkt för alla ohanterade undantag i appen, förhindrar krascher
  • iOS NSSetUncaughtExceptionHandler — C-funktion för att fånga Objective-C-undantag på Apple-plattformen
  • Android Thread.setDefaultUncaughtExceptionHandler — inbyggd plattformsmekanism för global undantagsfångst
  • Loggning före avslutning — hanterarens huvuduppgift: spara crash-information innan processen avslutas
  • Graceful degradation — hanteraren kan visa en korrekt felbild istället för en plötslig avstängning

Vad är Global Exception Handler?

Global Exception Handler — är en centraliserad mekanism för att fånga undantag som inte har hanterats på nivån av enskilda funktioner eller moduler i applikationen. I mobilutvecklingssammanhang fungerar en sådan hanterare som den sista försvarslinjen innan processen tvångsavslutas.

iOS och Android tillhandahåller inbyggda API:er för att installera en global hanterare. Apple använder NSSetUncaughtExceptionHandler för Objective-C-miljön och Google erbjuder Thread.setDefaultUncaughtExceptionHandler i Java/Kotlin. Båda mekanismerna fångar undantag som inte har fångats av try-catch-konstruktioner i alla appens trådar.

Enligt Crashlytics (Google, 2024) inträffar cirka 25% av krascherna på grund av ohanterade undantag i bakgrundstrådar — ett område där Global Exception Handler är särskilt kritisk. Utvecklare fokuserar ofta på UI-tråden och glömmer asynkrona operationer.

Att använda en global hanterare ersätter inte lokal felhantering utan kompletterar den. Huvuduppgiften är att spara maximal information om applikationens tillstånd vid undantagstillfället och avsluta korrekt.

Hur fungerar den globala undantagshanteraren

Funktionsmekanism — Global Exception Handler bygger på att fånga operativsystemssignaler eller körtidsundantag. När kod kastar ett undantag som inte fångas av något try-catch-block överförs kontrollen till den förinställda hanteraren.

På iOS-plattformen registreras hanteraren via NSSetUncaughtExceptionHandler och får ett NSException-objekt med full stack trace. På Android används Thread.setDefaultUncaughtExceptionHandler som tar emot Thread och Throwable — detta ger tillgång till undantagstyp, meddelande och anropsstack.

Efter att ha mottagit crash-data utför hanteraren tre obligatoriska åtgärder: skriva logg till lokal lagring, skicka rapport till Crashlytics eller Sentry och avsluta applikationen korrekt. Enligt Apple WWDC 2023 är hanterarens arbetstid begränsad till 5 sekunder — därefter avslutas processen tvångsvis.

För Swift-applikationer från iOS 13 och framåt har Signals API introducerats, som inte bara hanterar undantag utan även operativsystemssignaler — SIGABRT, SIGSEGV och SIGBUS — och utökar hanterarens täckning till lågnivåminnesfel.

Implementering av Global Exception Handler på iOS

Implementering — den globala hanteraren på iOS kräver att en C-funktion ställs in via NSSetUncaughtExceptionHandler. Hanteraren anropas synkront vid ett ohanterat undantag och får full felkontext.

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

    // Spara crash-logg i lokal fil
    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);
}

Viktig egenskap för iOS-implementeringen: hanteraren fångar endast Objective-C-undantag. Swift-fel som använder throw-catch-mekanismen når inte denna hanterare — de kräver separat hantering via Swift Error Handling. Från iOS 14 rekommenderar Apple att kombinera NSSetUncaughtExceptionHandler med Signals API för maximal täckning.

Enligt Apple Technical Note TN2151 måste applikationen avslutas inom 5 sekunder efter att hanteraren anropats. Alla försök att fortsätta exekveringen efter att ha återvänt från hanteraren leder till odefinierat beteende och ytterligare krasch.

Implementering av Global Exception Handler på Android

Android erbjuder en mer flexibel mekanism för global undantagshantering via Thread.setDefaultUncaughtExceptionHandler. Hanteraren får en referens till tråden där undantaget inträffade och själva Throwable-objektet.

kotlin
class GlobalExceptionHandler : Thread.UncaughtExceptionHandler {

    override fun uncaughtException(thread: Thread, throwable: Throwable) {
        // Spara crash-logg i fil
        val stackTrace = throwable.stackTraceToString()
        val crashLog = "CRASH: ${thread.name}\n${stackTrace}"

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

        // Skicka till Crashlytics
        FirebaseCrashlytics.getInstance()
            .recordException(throwable)

        // Avsluta processen
        android.os.Process.killProcess(
            android.os.Process.myPid()
        )
    }
}

// Installation i Application.onCreate
class App : Application() {
    override fun onCreate() {
        super.onCreate()
        Thread.setDefaultUncaughtExceptionHandler(
            GlobalExceptionHandler()
        )
    }
}

Nyckelskillnad i Android-implementeringen: varje tråd har sin egen hanterare och setDefaultUncaughtExceptionHandler ställer in en hanterare för alla trådar som inte har en individuell hanterare. Detta säkerställer global täckning — från UI-tråden till bakgrunds-AsyncTask och korutiner.

Från Android 12+ har en begränsning införts: efter anrop av uncaughtException måste applikationen avslutas inom 100 millisekunder. Om hanteraren utför långvariga operationer kan systemet döda processen innan loggskrivningen är klar. Det rekommenderas att använda en bakgrundstjänst för att skicka crash-rapporten.

Bästa praxis för Global Exception Handler

Första regeln — försök inte återställa applikationen efter ett ohanterat undantag. Applikationens tillstånd efter en krasch är odefinierat och att fortsätta arbetet kan leda till skada på användardata.

Minimera hanterarens arbetstid

Tidsbegränsning — den främsta tekniska begränsningen för Global Exception Handler. På iOS är detta 5 sekunder, på Android — 100 millisekunder. Inuti hanteraren är endast lagring av minimal data tillåten: undantagstyp, anropsstack och tillståndet för några nyckelvariabler.

Nätverksförfrågningar, databasskrivning och komplex serialisering bör flyttas till en fördröjd mekanism — till exempel spara loggen i en fil och skicka den vid nästa appstart.

Kombination med crash-rapporteringssystem

Crash-rapporteringstjänster — Firebase Crashlytics, Sentry, Bugsnag — installerar själva en global hanterare. Om utvecklaren installerar sin egen hanterare ovanpå dem måste han överlämna kontrollen till crash-rapporteringssystemet efter sina åtgärder. På Android används hanterarkomposition: utför egen logik, anropa sedan föregående hanterare.

För Firebase Crashlytics rekommenderas att inte alls installera en anpassad Thread.setDefaultUncaughtExceptionHandler — Crashlytics SDK gör detta automatiskt vid initiering.

Loggning av ytterligare information

Användarkontext — förutom standardanropsstacken är det bra att logga appversion, OS-version, mängden ledigt minne och tid till krasch. Dessa data är avgörande för reproduktion och åtgärdande av problemet.

På iOS kan NSSetUncaughtExceptionHandler användas inte bara för loggning utan även för tillfällig lagring av data i NSUserDefaults med synchronize-flaggan — detta garanterar att data bevaras även vid omedelbar processavslutning.

Testa hanteraren före lansering

Obligatorisk testning — Global Exception Handler måste testas i varje steg av CI/CD. På iOS kan ett testundantag initieras via @throw NSException, på Android — via throw RuntimeException(). Det kontrolleras att hanteraren anropas, loggen sparas och applikationen avslutas korrekt.

Enligt Google I/O 2023 inträffar mer än 30% av krascherna i produktion på enheter som utvecklaren inte testat — olika Android-versioner, anpassad firmware, begränsat minne.

Vanliga misstag vid användning av hanteraren

Första och vanligaste misstaget — försök att fortsätta exekveringen av applikationen efter att undantaget har hanterats. Efter anrop av uncaughtException är applikationen i ett instabilt tillstånd och ytterligare operationer kan orsaka kaskadfel och dataskador.

Andra misstaget — att utföra långvariga operationer inuti hanteraren. Nätverksförfrågningar, skrivning av stora filer eller komplexa beräkningar hinner inte slutföras innan processen tvångsavslutas. Enligt Apple Technical Q&A QA1468 är försök att skicka en HTTP-förfrågan inuti hanteraren den främsta orsaken till förlorade crash-rapporter.

Tredje misstaget — ignorering av bakgrundstrådar. En Global Exception Handler som bara är inställd för huvudtråden skyddar inte mot krascher i korutiner, DispatchQueue, AsyncTask eller RxJava. På Android bör varje tråd ha sin egen hanterare — och setDefaultUncaughtExceptionHandler löser detta problem endast för trådar utan individuell hanterare.

Fjärde misstaget — avsaknad av reservplan för operativsystemssignaler. NSSetUncaughtExceptionHandler på iOS fångar inte SIGABRT, SIGSEGV och SIGBUS. För dessa signaler krävs separat installation av hanterare via sigaction API. Utvecklare får reda på detta först när applikationen kraschar utan någon crash-rapport.

Femte misstaget — loggning av konfidentiell data. E-postmeddelanden, auktoriseringstoken eller personuppgifter hamnar i crash-loggarna. Detta bryter mot GDPR och Apple App Store Review Guidelines. Filtrera alltid överförd data via regex eller en vitlista över tillåtna fält.

Vanliga frågor

Kan applikationen återställas efter ett globalt undantag?

Nej — efter anrop av Global Exception Handler är applikationens tillstånd odefinierat. Alla försök att fortsätta arbetet kan leda till dataskador. Den enda korrekta åtgärden är att spara crash-logg och avsluta processen.

Fångar Global Exception Handler alla typer av fel?

Inte alla — på iOS fångar NSSetUncaughtExceptionHandler endast Objective-C-undantag. Swift-fel och operativsystemssignaler (SIGSEGV, SIGABRT) kräver separata hanterare. På Android fångar Thread.setDefaultUncaughtExceptionHandler alla RuntimeException men inte native-kodfel via JNI.

Hur överlämnar man kontrollen till crash-rapporteringssystemet efter sin egen hanterare?

Spara en referens till föregående hanterare via Thread.getDefaultUncaughtExceptionHandler() innan du installerar din egen hanterare. I slutet av din hanterare, anropa previousHandler.uncaughtException(thread, throwable) — detta garanterar att Crashlytics eller Sentry får sina data.

Vad gör man om kraschen inträffade i C/C++ native-kod?

För native-kod krävs signalhantering via sigaction() — SIGSEGV, SIGABRT, SIGBUS. På Android kan Google Breakpad eller Crashpad användas. På iOS från version 13 finns Signals API för hantering av mach-undantag.

Kan Global Exception Handler påverka prestandan?

Nej — installation av hanteraren påverkar endast vid undantagstillfället. Vid normal applikationsdrift finns ingen overhead. Den enda risken är minnesläcka om hanteraren håller en referens till Activity eller Context, vilket förhindrar deras sophämtning.

Sammanfattning

  • Global Exception Handler — sista försvarslinjen före krasch, obligatorisk i varje produktionsapplikation
  • iOS NSSetUncaughtExceptionHandler fångar Objective-C-undantag med en bearbetningsgräns på 5 sekunder
  • Android Thread.setDefaultUncaughtExceptionHandler fungerar för alla trådar utan personlig hanterare
  • Hanterarens arbetstid måste vara minimal — spara data och avsluta processen utan återställningsförsök
  • Operativsystemssignaler (SIGSEGV, SIGABRT) fångas inte av standardhanterare — sigaction API krävs
  • Crash-rapporteringssystem bör anropas via hanterarkomposition med kontrollöverlämning efter egen logik
  • Testning av hanteraren i CI/CD — obligatorisk fas som förhindrar förlust av crash-rapporter i produktion

Vi utvecklar en mobil applikation nyckelfärdigt

IT Sectr skapar iOS- och Android-applikationer för startups och företag sedan 2017. Vi ger dig råd och föreslår den bästa lösningen.

Diskutera projektet

Läs också