Crash aplikacji: co to jest, przyczyny zamykania i metody wykrywania

Autor: IT Sectr Opublikowano: 2026-07-27 Czas czytania: 7 min

Crash aplikacji — awaryjne zakończenie, w którym program przestaje odpowiadać i zamyka się. W mobilnym developmentcie crashe są głównym źródłem negatywnych opinii i spadku ocen. Według danych Firebase (2024), użytkownicy usuwają aplikację po jednym-dwóch crashach w 53% przypadków. Każde zamknięcie zmniejsza retention o 3–5%. Systemy monitorowania takie jak Crashlytics i Sentry pomagają szybko znajdować i naprawiać przyczyny awarii, zanim dotkną one masowo użytkowników.

Najważniejsze

  • Crash — nieoczekiwane zakończenie aplikacji z powodu nieobsłużonego błędu wykonania
  • Główne przyczyny — NullPointerException, OutOfMemoryError, IndexOutOfBounds, ANR w Android
  • Crashlytics — standard monitorowania crashy z automatycznym zbieraniem stack trace i grupowaniem
  • Runtime exceptions — wyjątki, których kompilator nie sprawdza, ujawniają się tylko w czasie wykonania
  • Strategie zapobiegania — silna typizacja, optional binding, error handling i testowanie

Co to jest crash aplikacji

Crash — nieoczekiwane zakończenie programu spowodowane wyjątkową sytuacją, której kod nie obsłużył. W mobilnych systemach operacyjnych crash prowadzi do natychmiastowego zamknięcia aplikacji i wyświetlenia ekranu „Aplikacja została zatrzymana” lub powrotu do ekranu głównego.

Crashe dzielą się na dwie duże klasy. Błędy obsłużone — bloki try/catch przechwytują wyjątek, aplikacja kontynuuje działanie, możliwie z utratą funkcjonalności. Nieobsłużone crashe — wyjątek propaguje się do poziomu systemu operacyjnego, który zabija proces. Drugi typ jest szczególnie niebezpieczny, ponieważ użytkownik nie może zapisać danych.

System z dwoma milionami użytkowników i wskaźnikiem crash rate 0,1% traci 2 000 użytkowników przy każdym wydaniu. Według Google Play Console (2024), aplikacje z crash rate powyżej 1,5% są wykluczane z rekomendacji i tracą do 30% organicznego ruchu.

Główne przyczyny zamykania w aplikacjach mobilnych

NullPointerException (NPE) — król crashy w Java/Kotlin. Próba wywołania metody na null-obiekcie. W Kotlin NPE występuje rzadziej dzięki null safety, ale wciąż jest możliwy przy użyciu operatora !! lub interakcji z kodem Java. Google (2024) szacuje: NPE stanowi 25% wszystkich crashy aplikacji Android.

IndexOutOfBoundsException — odwołanie do elementu listy po nieistniejącym indeksie. Częsta przyczyna: dane przyszły z serwera w nieoczekiwanym formacie, a UI próbuje wyświetlić pozycję, której nie ma. Rozwiązanie — zawsze sprawdzaj rozmiar kolekcji przed dostępem przez indeks.

ANR (Application Not Responding) — problem specyficzny dla Androida. Wątek UI jest blokowany na więcej niż 5 sekund. Główne przyczyny: żądania sieciowe na głównym wątku, ciężkie obliczenia, synchronizacja z bazą danych. StrictMode w Android pomaga wykryć blokady wątku UI na etapie developmentu.

OutOfMemoryError (OOM) — aplikacja przekroczyła limit pamięci. W urządzeniach mobilnych z 2–4 GB RAM OOM to częsty problem przy pracy z dużymi obrazami lub nieskończonymi listami bez paginacji. Rozwiązanie — Glide/Coil do ładowania obrazów, LruCache do cachowania, ViewHolder w RecyclerView.

Runtime exceptions i błędy krytyczne

Runtime exceptions — błędy, których kompilator nie sprawdza na etapie budowania. Ujawniają się tylko podczas wykonania kodu na konkretnym urządzeniu z konkretnymi danymi. W Java to RuntimeException i jego podklasy: NullPointerException, IllegalArgumentException, ArithmeticException.

Błędy krytyczne (FATAL) — nie runtime, ale awarie systemowe. Signal 11 (SIGSEGV) — naruszenie segmentacji pamięci w kodzie native. Signal 6 (SIGABRT) — awaryjne zakończenie wywołane przez samą aplikację przez abort(). Takie crashe są trudne do zdiagnozowania, ponieważ stack trace często nie pokazuje zrozumiałego kontekstu.

W iOS główne przyczyny to NSInvalidArgumentException (nieoczekiwany nil w parametrze) i EXC_BAD_ACCESS (dostęp do zwolnionej pamięci). Swift zmniejszył liczbę crashy w porównaniu z Objective-C, ale błędy w runtime ObjC i bibliotekach C wciąż prowadzą do awarii.

Monitorowanie i zbieranie logów crashy

Firebase Crashlytics — standard dla aplikacji mobilnych. Automatycznie zbiera stack trace, dodaje logi, ID użytkownika i metadane urządzenia. Grupuje crashe według sygnatury (klasa błędu + linia). Real-time alerts — powiadomienia, gdy crash rate przekracza zadany próg (np. >0,1% na godzinę).

Sentry — alternatywa z bardziej elastycznymi możliwościami. Pozwala tworzyć custom contexts, dodawać breadcrumbs (poprzedzające zdarzenia), konfigurować in-app filtering do wykluczania nieistotnych błędów. Source maps dla Kotlin i Swift pozwalają widzieć kod źródłowy, a nie zaciemnione nazwy.

Best practices dla logów: wysyłaj kluczowe metadane przed wykonaniem niebezpiecznej operacji — wtedy w logu będzie widoczne, co robił użytkownik przed crashem. Dodawaj custom keys (numer wersji API, ostatni ekran, rozmiar danych wejściowych). To zamienia bezużyteczny stack trace w użyteczną informację.

Przykład: konfiguracja Crashlytics w Android

kotlin
class PaymentViewModel : ViewModel() {
    fun processPayment(amount: Double) {
        crashlytics.setCustomKey("last_screen", "payment")
        crashlytics.setCustomKey("amount", amount)
        try {
            api.charge(amount)
        } catch (e: Exception) {
            crashlytics.recordException(e)
        }
    }
}

Strategie zapobiegania crashom

Optional binding i null safety — w Kotlin używaj `?` dla typów nullable, `let` i `?:` do bezpiecznego przetwarzania null. W Swift — optionals i guard let. Modern Kotlin (2024) dodał adnotacje Contract: `@ContractsDsl` pozwala zadeklarować, że funkcja nie zwraca null, a kompilator to sprawdza.

Error handling w sieci — każde żądanie sieciowe powinno obsługiwać timeout, błędy parsowania i odmowę serwera. Retrofit z typem Result — sealed class, która gwarantuje, że błąd zostanie obsłużony. Styl No Exception: zamiast try/catch używaj sealed Result do jawnego obsłużenia sukcesu i błędu.

Feature flags — wyłączaj problematyczną funkcjonalność zdalnie bez wydawania nowej wersji. Jeśli operacja serwerowa powoduje crash na starych urządzeniach — flaga wyłącza ją dla tej grupy. Firebase Remote Config pozwala zmieniać zachowanie aplikacji bez publikacji w sklepie.

Stopniowy rollout — wydawaj nową wersję na 5% odbiorców i monitoruj crash rate. Jeśli rate pozostaje poniżej docelowego (zwykle <0,1%), rozszerzaj do 25%, potem 50%, potem 100%. Google Play Console i App Store Connect obsługują staged rollouts do automatycznego zatrzymania przy przekroczeniu progu.

Plan działania po wykryciu błędu

Krok 1: Klasyfikacja — określ severity: Critical (crash u >1% użytkowników), High (0,1–1%), Medium (<0,1%). Dla Critical crashy — immediate response. Dla pozostałych — standardowy proces naprawy błędu w bieżącym sprincie. Google Play Console automatycznie klasyfikuje crashe według liczby dotkniętych użytkowników.

Krok 2: Analiza stack trace — otwórz log w Crashlytics, zobacz dokładne miejsce awarii. Sprawdź custom keys: jaki ekran, jakie dane, wersja OS. Porównaj z ostatnim wdrożeniem — często crash jest spowodowany świeżą zmianą w kodzie, która dotknęła nieoczekiwany scenariusz użycia.

Krok 3: Odtworzenie — spróbuj odtworzyć crash na urządzeniu lub emulatorze z podobnymi parametrami. Jeśli się nie udaje — sprawdź crash log pod kątem wzorców: konkretne modele (Samsung A10), wersje Android (API < 26), locale. Rozwiązanie — dodaj warunek zabezpieczający, który pokrywa scenariusz.

Krok 4: Fix i monitorowanie — wydaj hotfix z priorytetem. Po wydaniu upewnij się, że crash rate dla tego typu spada do zera. Napisz test regresyjny, który pokrywa scenariusz crasha. Bez testu ten sam błąd może powrócić przy następnym refaktoringu.

Często zadawane pytania

Jaki crash rate jest uważany za normalny?

Normalny crash rate — poniżej 0,1% dla wydań produkcyjnych. Google Play zaleca utrzymywanie crash rate poniżej 1,5%, ale topowe aplikacje (YouTube, Instagram) utrzymują 0,01–0,05%. Dla wydań nowej funkcjonalności dopuszcza się tymczasowy wzrost do 0,5% z późniejszym spadkiem po hotfixie.

Czym różni się crash od ANR?

Crash — aplikacja kończy się awaryjnie. ANR (Application Not Responding) — aplikacja zawiesza się na więcej niż 5 sekund, ale nie zamyka się przymusowo. Użytkownik widzi dialog „Aplikacja nie odpowiada” i może poczekać lub zamknąć. Problemy ANR są nie mniej poważne niż crashe i również wpływają na ocenę w sklepie.

Dlaczego crash może występować nie na wszystkich urządzeniach?

Różne urządzenia mają różne wersje OS, ilość pamięci, wersje bibliotek, a nawet procesory. Przykład: crash na Android 6 (API 23) z powodu braku runtime permission może nie występować na Android 12. Analizuj crash log według filtrów: OS version, device model, amount of RAM. To wskaże specyfikę problemu.

Jak znaleźć przyczynę crasha, jeśli stack trace jest nieinformatywny?

Dodaj custom breadcrumbs w Crashlytics: zapisuj kluczowe zdarzenia przed wykonaniem operacji. Jeśli crash występuje na 3. kroku onboardingu — to wskazuje na problem w konkretnym ekranie. Debug symbols (dSYM, ProGuard mapping) — koniecznie przesyłaj do Crashlytics, aby widzieć rzeczywiste nazwy funkcji, a nie zaciemnione.

Czy należy crashować aplikację przy niekrytycznych błędach?

W production — nigdy. Nieobsłużony crash pogarsza doświadczenie użytkownika. Używaj try/catch z logowaniem błędu. W trybie debug dopuszczalne jest crashowanie dla szybkiej informacji zwrotnej dla developera. Assertions — do sprawdzania niezmienników, które nigdy nie powinny być naruszone, ale tylko w kompilacjach debug.

Podsumowanie

  • Crash — awaryjne zakończenie aplikacji prowadzące do utraty użytkowników i spadku ocen w sklepach
  • NullPointerException — najczęstsza przyczyna crashy w aplikacjach mobilnych (25% wszystkich awarii)
  • ANR i OOM — krytyczne problemy specyficzne dla Androida, wymagające osobnego monitorowania i profilaktyki
  • Crashlytics i Sentry — główne narzędzia zbierania stack trace z grupowaniem i powiadomieniami w czasie rzeczywistym
  • Error handling — optional binding, typy sealed Result i zabezpieczenia zapobiegają większości crashy
  • Feature flags i staged rollout — zmniejszają wpływ błędów na odbiorców, pozwalając wycofać problematyczny kod
  • Po naprawie crasha obowiązkowy jest test regresyjny, wykluczający nawrót problemu

Opracujemy aplikację mobilną pod klucz

IT Sectr tworzy aplikacje na iOS i Androida dla startupów i firm od 2017 roku. Doradzimy Ci i zaproponujemy najlepsze rozwiązanie.

Omów projekt

Przeczytaj również