Crash — a mobilalkalmazás váratlan leállása egy nem kezelt kivétel vagy végzetes rendszerhiba miatt. A Firebase Crashlytics adatai szerint a felhasználók körülbelül 2%-a tapasztal naponta összeomlást, és minden egyes összeomlás 10–20%-kal csökkenti a retenciót. Az okok és az összeomlások megelőzési módszereinek megértése kötelező készség a mobilfejlesztő számára.
Főbb pontok
Crash — az alkalmazás váratlan leállása, amelyet egy nem kezelt kivétel vagy végzetes rendszerjelzés okoz, amelyet nem kezeltek az alkalmazás kódjában. Amikor a rendszer vagy a virtuális gép (JVM, ART) végzetes állapotot észlel — NullPointerException, IndexOutOfBoundsException, OutOfMemoryError — azonnal leállítja a folyamatot és eltávolítja a memóriából. A felhasználó az alkalmazás hirtelen bezáródását látja, bármilyen rendszerhiba-értesítés nélkül. A Google adatai szerint azok az alkalmazások, amelyek crash-free aránya 99% alatt van, havonta akár 20%-át is elveszítik aktív felhasználóiknak.
Androidon az összeomláskezelés mechanizmusa eltér az asztali rendszerektől. A stack trace-szel ellátott hibakeresési párbeszédpanel helyett az Android egyszerűen megöli a folyamatot és nem menti a részletes információkat. Az összeomlási információk gyűjtése harmadik fél könyvtárainak (Crashlytics, Sentry, Bugsnag) feladata, amelyek a Thread.setDefaultUncaughtExceptionHandler segítségével fogják el a kivételeket, mielőtt a folyamat befejeződik.
iOS hasonló mechanizmust használ az NSException és Mach exceptions segítségével a végzetes hibák kezelésére. Nem kezelt kivétel esetén a rendszer befejezi az alkalmazást, és a jelentés .crash fájlként kerül mentésre. Az összeomlások gyűjtése iOS-en integrációt igényel a Crashlytics-szel vagy a beépített jelentéssel az Xcode Organizeren keresztül.
Öt kategória fedi le az összes összeomlás 90%-át a mobilalkalmazásokban. Az egyes típusok megértése segít a problémák gyorsabb diagnosztizálásában és javításában éles környezetben.
NullPointerException (NPE) — a leggyakoribb összeomlástípus az összes Java/Kotlin alkalmazásban. Akkor keletkezik, amikor megpróbálunk meghívni egy metódust vagy hozzáférni egy null értékű objektum mezőjéhez. Tipikus forgatókönyvek: inicializálatlan Activity mező képernyőforgatáskor, null válasz a szervertől JSON deszerializációkor, gondatlan navigáció a RecyclerView adapteren keresztül.
A Kotlin az NPE problémát nyelvi szinten oldja meg null-biztos típusokkal: a String? nem használható explicit ellenőrzés nélkül. A Java kompatibilitás és a Reflection azonban továbbra is kockázatot jelent. Használja a @NonNull és @Nullable annotációkat, és kapcsolja be a strictNullChecks-et a statikus elemző eszközökben.
fun safeLength(text: String?): Int {
return text?.length ?: 0 // null biztonságos kezelése
}
IndexOutOfBoundsException akkor keletkezik, amikor egy lista vagy tömb nem létező indexéhez férünk hozzá. Gyakori forgatókönyv: elem eltávolítása a RecyclerView-ból az adapterrel való szinkronizálás nélkül, ArrayList több szálú módosítása zárolás nélkül, pozíció hibás kiszámítása a ViewPager-ben. A ConcurrentModificationException — közeli rokon a gyűjtemények egyidejű iterálásakor és módosításakor.
Több szálú hozzáféréshez használja a CopyOnWriteArrayList-t vagy a Lock-free gyűjteményeket a java.util.concurrent csomagból. Az UI-val való szinkronizáláshoz alkalmazza a DiffUtil-t, amely biztonságosan és hatékonyan számítja ki a régi és új lista közötti különbséget.
ClassCastException akkor keletkezik, amikor egy objektumot nem kompatibilis típusra konvertálunk. Androidban tipikus okok: helytelen ViewHolder típus a RecyclerView-ban (különböző cellatípusok helyes getItemViewType nélkül), helytelen Fragment konverzió navigációnál, Serializable objektumok eltérő osztályverziókkal.
Használja a Kotlin biztonságos konverzióját az as? operátoron keresztül, amely null-t ad vissza típus-összeférhetetlenség esetén. Java-ban — ellenőrzés instanceof segítségével a konvertálás előtt. Parcelable objektumoknál kötelező a CREATOR deklarálása minden osztályban.
IllegalStateException jelzi, hogy egy metódust az objektum nem megfelelő állapotában hívtak meg. Tipikus példa Androidban — getSupportFragmentManager() az onSaveInstanceState után, amikor a fragment commit() nem engedélyezett. Egy másik gyakori eset — a dismiss() meghívása egy már bezárt párbeszédablakon.
Ellenőrizze az életciklus állapotát a FragmentManager műveletek előtt. Csak akkor használja a commitAllowingStateLoss()-t, ha biztos benne, hogy az állapotvesztés nem kritikus. Kotlinban hozzon létre DSL-szerű építőket, amelyek kizárják a helytelen állapotokat típus szinten.
Native Crash natív C/C++ kódban keletkezik memóriamegsértéskor: null mutatón keresztüli hozzáférés, double-free, verem puffer túlcsordulása. Androidban ilyen összeomlások NDK könyvtárakban, játékmotorokban (Unity, Unreal) és rendszerfüggőségekben fordulnak elő. A Native Crash-t NEM fogja el a Thread.setDefaultUncaughtExceptionHandler — azonnal megöli a folyamatot.
Natív összeomlások diagnosztizálásához használjon minidump fájlokat (Breakpad) vagy Android tombstone-okat. A Firebase Crashlytics támogatja a natív összeomlások gyűjtését az NDK SDK-n keresztül. iOS-en a hasonló probléma a PLCrashReporter segítségével oldható meg.
Három eszköz uralja a mobil összeomlás-jelentés piacát. Mindegyik stack trace gyűjtést, alkalmazásverziók szerinti aggregációt és értesítéseket biztosít az új összeomlásokról.
Crashlytics — a legnépszerűbb összeomlás-jelentő mobilalkalmazásokhoz, amely a Firebase ökoszisztéma része. Automatikusan gyűjti a stack trace-t, eszközadatokat, operációs rendszer verzióját és a felhasználó egyedi kulcsait. Az integráció 10 percet vesz igénybe a Firebase Console-on és a Gradle Plugin-en keresztül. A Crashlytics támogatja a valós naplókat (Logcat) és az egyedi követést is.
FirebaseCrashlytics.getInstance()
.setCustomKey("current_screen", "ProfileFragment")
FirebaseCrashlytics.getInstance()
.log("User tapped login button")
Sentry — alternatíva a Crashlytics-hez, rugalmasabb szűrőrendszerrel és 90+ platform támogatásával. A Firebase-től eltérően a Sentry saját üzemeltetésű szervert (self-hosted) kínál azon cégek számára, amelyek szigorú adatkövetelményekkel rendelkeznek. A Sentry támogatja a disztributív követést, a breadcrumbs-eket és a CI/CD pipeline-okkal való integrációt.
Bugsnag a súlyosság-alapú riasztások támogatásával tűnik ki: az összeomlásokat kritikus, hiba és figyelmeztetés kategóriákra osztja. A Microsoft AppCenter-e — ingyenes eszköz alapfunkciókkal kisebb projektek számára. Mindkettő támogatja az Android, iOS, React Native és Flutter platformokat.
Az összeomlás elemzése az esemény teljes képének rekonstruálásának folyamata. A stack trace csak az utolsó hibapontot mutatja, de nem ad kontextust arról, hogy mi vezetett a problémához. A professzionális megközelítés négy szakaszból áll.
Első szakasz — a stack trace olvasása. Határozza meg azt az osztályt, metódust és kódsort, ahol a kivétel történt. Kövesse a hívási láncot a felső kerettől az alsó felé: a verem utolsó sora az összeomlás helye, a felső sorok pedig a hívások sorrendjét mutatják. A deobfuszkáció (ProGuard/R8 mapping) kötelező az éles build-eknél.
Második szakasz — eszközkontextus. A Crashlytics mutatja az eszközmodellt, az operációs rendszer verzióját, a rendelkezésre álló memóriát és az alkalmazás verzióját. Például, ha az összeomlás csak Samsung Galaxy S10-en történik Android 11-gyel, az egy adott One UI verzióval kapcsolatos problémára utal, nem általános kódhibára.
Harmadik szakasz — reprodukálás teszteszközön. Ha az összeomlás nem reprodukálható stabilan, kérdezze meg a felhasználót a pontos lépésekről, vagy használja a Remote Config-ot a naplózáshoz a problémás kódrészlet előtt. AB-tesztelés a javítás kipróbálása a közönség egy részén segít megerősíteni a megoldást.
Negyedik szakasz — monitorozás a javítás után. A javítás közzététele után figyelje az összeomlások gyakoriságát 3–5 napig. Ha az összeomlás teljesen eltűnt — a javítás működött. Ha a gyakoriság csökkent, de nem nullázódott — létezik egy második forgatókönyv, amely külön elemzést igényel.
Szisztematikus megközelítés az összeomlások megelőzéséhez magában foglalja a statikus elemző eszközöket, a szélsőséges esetek kötelező tesztelését és a hibák megfelelő kezelését az alkalmazás minden szintjén.
Detekt (Kotlin) és Lint (Android) a fordítás fázisában találja meg a potenciális problémákat: nem használt változók, potenciális NPE, API helytelen használata. Kapcsolja be ezeket az eszközöket a CI pipeline-ban hiba küszöbértékkel. Például a Detekt 30+ figyelmeztetés vagy bármilyen error-blocking konfigurációval nem engedi át a build-et.
A kulcsfontosságú használati forgatókönyvek lefedettsége unit tesztekkel az alapvető védelem a regressziós összeomlások ellen. Tesztelje az adatmodelleket, ViewModel-t és UseCase rétegeket szélsőséges esetekkel: null értékek, üres listák, érvénytelen JSON. Az UI tesztek Espresso vagy Compose Test segítségével fedik le a kritikus folyamatokat: hitelesítés, fizetés, bevezetés.
Tervezze az alkalmazást úgy, hogy egy modul hibája ne döntse le az egész képernyőt. Használjon catch blokkokat a ViewModel szintjén tartalék állapot visszaadásával: helyőrző megjelenítése lista helyett, gyorsítótárazott adatok hálózat hiányában, tartalék kép betöltési hiba esetén. Ez a potenciális összeomlást kontrollált UX forgatókönyvvé alakítja.
Staged rollouts — a Google Play és App Store szabványos gyakorlata: az új verziót először a közönség 5%-ának, majd 20%-ának, végül 100%-ának terjesztik ki 1–3 napos időközönként. Minden szakaszban figyelik az összeomlások gyakoriságát: ha a crash-free arány 99,5% alá csökken, a bevezetés automatikusan leáll. A Firebase Remote Config lehetővé teszi a problémás funkciók kikapcsolását anélkül, hogy új verziót kellene közzétenni.
Renovate vagy Dependabot a CI-ben automatikusan ellenőrzi a könyvtárakat ismert sebezhetőségekre és kritikus hibákra. Egyetlen függőség frissítése megszüntetheti az összeomlások egy egész osztályát. Azonban tesztelje a frissítéseket staging környezetben, mielőtt éles környezetbe helyezné — a könyvtár új verziója nem kompatibilis változtatásokat tartalmazhat.
Gyakran Ismételt Kérdések
Nem. Az összeomlások egy részét a fejlesztő irányításán kívül eső tényezők okozzák: rendszerhibák, hardverproblémák, firmware-inkompatibilitás. A cél a gyakoriság 0,1%-ra vagy az alá csökkentése, a fennmaradó összeomlások minimalizálása a reakcióidő szempontjából.
Az összeomlás-jelentő stack trace-t, memóriaállapotot és eszközinformációkat gyűjt az összeomlás pillanatában. Az analitika a felhasználó viselkedési adatait gyűjti. A Crashlytics mindkét megközelítést ötvözi, az összeomlás kontextusát a felhasználó egyedi kulcsaival együtt biztosítva.
A ProGuard és az R8 a szellemi tulajdon védelme érdekében homályosítja el a kódot. A deobfuszkációhoz töltse fel a mapping fájlt a Crashlytics-be a közzétételkor. Mapping fájl nélkül a stack trace a.a(), b.b() értékeket mutat a valódi osztály- és metódusnevek helyett.
Androidon a Thread.setDefaultUncaughtExceptionHandler segítségével: a könyvtár regisztrálja saját kezelőjét, amely elsőként kapja meg a nem kezelt kivételt, elmenti az adatokat, és csak azután fejezi be a folyamatot. iOS-en az NSSetUncaughtExceptionHandler-t használják az NSException-hez és Mach exception handlert a jelekhez.
Fatal — az alkalmazás leállt. Non-fatal (elkapott kivétel) — a fejlesztő elkapott egy kivételt try-catch segítségével, de ez potenciális problémára utalhat. A Crashlytics megkülönbözteti ezeket a típusokat, és lehetővé teszi a non-fatal külön szűrését, hogy ne zavarja el az irányítópultot.
Összefoglalás
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.
Olvassa el is