Crash у мобилном развоју: шта је, врсте и методе спречавања

Аутор: IT Sectr Објављено: 2026-03-29 Време читања: 9 мин

Crash — хитно заустављање мобилне апликације због необрађеног изузетка или фаталног системског квара. Према подацима Firebase Crashlytics, око 2% корисника се свакодневно сусреће са падовима, а сваки пад смањује ретенцију за 10–20%. Разумевање узрока и метода спречавања падова је обавезна вештина за мобилног програмера.

Главно

  • Crash — необрађени изузетак који доводи до хитног заустављања процеса
  • NullPointerException — најчешћи тип пада у Java/Kotlin апликацијама
  • Извештачи падова прикупљају stack trace, стање уређаја и корисничке податке
  • Firebase Crashlytics — стандардни алат за праћење падова у мобилном развоју
  • Спречавање укључује правилно руковање грешкама, тестирање и проверу null-безбедности

Шта је Crash

Crash — је хитно заустављање апликације узроковано необрађеним изузетком или фаталним системским сигналом који није обрађен у коду апликације. Када систем или виртуелна машина (JVM, ART) открије фатално стање — NullPointerException, IndexOutOfBoundsException, OutOfMemoryError — одмах зауставља процес и уклања га из меморије. Корисник види изненадно затварање апликације без икакве системске обавештења о грешци. Према Google-у, апликације са crash-free стопом испод 99% губе до 20% активних корисника месечно.

На Android-у механизам обраде падова се разликује од десктоп система. Уместо дијалога за отклањање грешака са stack trace-ом, Android једноставно убија процес и не чува детаљне информације. Прикупљање информација о паду је задатак библиотека трећих страна (Crashlytics, Sentry, Bugsnag), које пресрећу изузетке преко Thread.setDefaultUncaughtExceptionHandler пре него што се процес заврши.

iOS користи сличан механизам са NSException и Mach exceptions за обраду фаталних грешака. При необрађеном изузетку, систем завршава апликацију, а извештај се чува у облику .crash фајла. Прикупљање падова на iOS-у захтева интеграцију са Crashlytics-ом или уграђеним извештајем преко Xcode Organizer-а.

Главни типови падова

Пет категорија падова покрива 90% свих падова у мобилним апликацијама. Разумевање сваког типа помаже у бржој дијагнози и поправци проблема у продукцији.

NullPointerException — краљ падова

NullPointerException (NPE) — најраспрострањенији тип пада у свим Java/Kotlin апликацијама. Настаје при покушају позивања методе или приступа пољу објекта који је null. Типични сценарији: неиницијализовано поље Activity при ротацији екрана, null-одговор од сервера при десеријализацији JSON-а, непажљива навигација кроз адаптер RecyclerView-а.

Kotlin решава проблем NPE на нивоу језика кроз null-безбедне типове: String? не може се користити без експлицитне провере. Међутим, компатибилност са Java-ом и Reflection и даље стварају ризике. Користите анотације @NonNull и @Nullable и укључите strictNullChecks у алатима статичке анализе.

kotlin
fun safeLength(text: String?): Int {
    return text?.length ?: 0 // безбедна обрада null
}

IndexOutOfBoundsException и грешке колекција

IndexOutOfBoundsException настаје при приступу непостојећем индексу листе или низа. Чест сценариј: уклањање елемента из RecyclerView-а без синхронизације са адаптером, више-нитејска модификација ArrayList-а без блокаде, нетачно израчунавање позиције у ViewPager-у. ConcurrentModificationException — блиски рођак при истовременој итерацији и модификацији колекција.

Користите CopyOnWriteArrayList за више-нитејски приступ или Lock-free колекције из java.util.concurrent. За синхронизацију са UI-јем примените DiffUtil, који безбедно и ефикасно израчунава разлику између старе и нове листе.

ClassCastException — типични проблеми

ClassCastException настаје при конвертовању објекта у некомпатибилан тип. У Android-у типични узроци: нетачан тип ViewHolder-а у RecyclerView-у (различити типови ћелија без исправног getItemViewType-а), нетачна конверзија Fragment-а при навигацији, Serializable објекти са различитим верзијама класа.

Користите безбедну конверзију Kotlin-а преко оператора as?, који враћа null при некомпатибилности типова. У Java-и — провера кроз instanceof пре конверзије. За Parcelable објекте обавезно декларишите CREATOR у свакој класи.

IllegalStateException и логичке грешке

IllegalStateException сигнализира позивање методе у неодговарајућем стању објекта. Типичан пример у Android-у — getSupportFragmentManager() после onSaveInstanceState, када commit() фрагмента није дозвољен. Други чест случај — позивање dismiss() на већ затвореном дијалогу.

Проверавајте стање животног циклуса пре операција са FragmentManager-ом. Користите commitAllowingStateLoss() само када сте сигурни да губитак стања није критичан. У Kotlin-у креирајте DSL-сличне градитеље који искључују неисправна стања на нивоу типова.

Native Crash (сигнали SIGSEGV, SIGABRT)

Native Crash настаје у изворном C/C++ коду при нарушавању меморије: приступ преко нултог показивача, double-free, прекорачење бафера стека. У Android-у такви падови настају у NDK библиотекама, играчким погонима (Unity, Unreal) и системским зависностима. Native Crash НЕ пресреће Thread.setDefaultUncaughtExceptionHandler — убија процес тренутно.

За дијагностику изворних падова користите minidump фајлове (Breakpad) или Android tombstone-ове. Firebase Crashlytics подржава прикупљање изворних падова преко NDK SDK-а. На iOS-у сличан проблем се решава кроз PLCrashReporter.

Алати за извештавање падова

Три алата доминирају на тржишту извештавања мобилних падова. Сваки пружа прикупљање stack trace-а, агрегацију по верзијама апликације и обавештења о новим падовима.

Firebase Crashlytics

Crashlytics — најпопуларнији извештач падова за мобилне апликације који је део Firebase екосистема. Аутоматски прикупља stack trace, податке о уређају, верзију оперативног система и корисничке прилагођене кључеве. Интеграција траје 10 минута кроз Firebase Console и Gradle Plugin. Crashlytics такође подржава стварне дневнике (Logcat) и прилагођено праћење.

kotlin
FirebaseCrashlytics.getInstance()
    .setCustomKey("current_screen", "ProfileFragment")

FirebaseCrashlytics.getInstance()
    .log("User tapped login button")

Sentry

Sentry — алтернатива Crashlytics-у са флексибилнијим системом филтрирања и подршком за 90+ платформи. За разлику од Firebase-а, Sentry пружа сопствени сервер (self-hosted) за компаније са строгим захтевима за податке. Sentry подржава дистрибутивно праћење, breadcrumbs и интеграцију са CI/CD цевоводима.

Bugsnag и AppCenter

Bugsnag се истиче подршком за аларме засноване на озбиљности: дели падове на критичне, грешке и упозорења. AppCenter од Microsoft-а — бесплатни алат са основном функционалношћу за мале пројекте. Оба подржавају Android, iOS, React Native и Flutter.

Како анализирати пад

Анализа пада је процес реконструкције потпуне слике догађаја. Stack trace показује само последњу тачку отказа, али не даје контекст који је довео до проблема. Професионални приступ укључује четири фазе.

Прва фаза — читање stack trace-а. Одредите класу, метод и линију кода где се догодио изузетак. Пратите ланац позива од горњег оквира ка доњем: последња линија у стеку је место пада, а горње линије су низ позива. Deobfuscation (ProGuard/R8 мапирање) је обавезан за продукцијске верзије.

Друга фаза — контекст уређаја. Crashlytics показује модел уређаја, верзију оперативног система, доступну меморију и верзију апликације. На пример, пад само на Samsung Galaxy S10 са Android 11 указује на проблем са одређеном верзијом One UI-ја, а не на општу грешку кода.

Трећа фаза — репродукција на тест уређају. Ако се пад не репродукује стабилно, питајте корисника за тачне кораке или користите Remote Config за евидентирање пре проблематичног дела кода. AB тестирање поправке на делу публике помаже у потврди решења.

Четврта фаза — праћење након поправке. Након објављивања поправке, посматрајте учесталост пада током 3–5 дана. Ако је пад потпуно нестао — поправка је успела. Ако се учесталост смањила, али није пала на нулу — постоји други сценариј који захтева посебну анализу.

Праксе спречавања падова

Систематски приступ спречавању падова укључује алате статичке анализе, обавезно тестирање граничних случајева и правилно руковање грешкама на свим нивоима апликације.

Статичка анализа кода

Detekt (Kotlin) и Lint (Android) проналазе потенцијалне проблеме у фази компилације: некоришћене променљиве, потенцијалне NPE, неправилно коришћење API-ја. Укључите ове алате у CI цевовод са прагом грешака. На пример, Detekt са конфигурацијом од 30+ упозорења или било које error-blocking не пропушта градњу.

Unit тестови и UI тестови

Покриће кључних сценарија коришћења unit тестовима је основна заштита од регресивних падова. Тестирајте моделе података, ViewModel и UseCase слојеве са граничним случајевима: null вредности, празне листе, неисправан JSON. UI тестови кроз Espresso или Compose Test покривају критичне токове: ауторизацију, плаћање, упознавање.

Graceful Degradation

Пројектујте апликацију тако да квар у једном модулу не обори цео екран. Користите catch блокове на нивоу ViewModel-а са враћањем резервног стања: приказ чувара места уместо листе, кеширани подаци при недостатку мреже, резервна слика при грешци учитавања. Ово претвара потенцијални пад у контролисани UX сценариј.

Постепено објављивање са праћењем

Staged rollouts — стандардна пракса Google Play-а и App Store-а: нова верзија се дистрибуира на 5%, затим на 20% и на 100% публике са интервалом од 1–3 дана. На свакој фази се прати учесталост падова: ако crash-free стопа падне испод 99.5%, објављивање се аутоматски зауставља. Firebase Remote Config омогућава искључивање проблематичних функција без објављивања нове верзије.

Контрола верзија зависности

Renovate или Dependabot у CI-ју аутоматски проверавају библиотеке за познате рањивости и критичне грешке. Ажурирање једне зависности може елиминисати читаву класу падова. Међутим, тестирајте ажурирања на staging окружењу пре објављивања у продукцију — нова верзија библиотеке може садржати некомпатибилне измене.

Често постављана питања

Може ли се спречити 100% падова?

Не. Део падова је изазван факторима ван контроле програмера: системске грешке, хардверски проблеми, некомпатибилност фирмвера. Циљ је смањити учесталост на 0.1% и ниже, а преостале падове минимизирати по времену реакције.

По чему се извештач падова разликује од аналитике?

Извештач падова прикупља stack trace, стање меморије и уређај у тренутку пада. Аналитика прикупља податке о понашању корисника. Crashlytics обједињује оба приступа, пружајући контекст пада заједно са корисничким прилагођеним кључевима.

Зашто је stack trace обојен?

ProGuard и R8 замрачују код за заштиту интелектуалне својине. За деобфускацију отпремите мапинг фајл у Crashlytics при објављивању. Без мапинг фајла, stack trace ће показати a.a(), b.b() уместо стварних имена класа и метода.

Како извештач падова пресреће изузетке?

Преко Thread.setDefaultUncaughtExceptionHandler на Android-у: библиотека региструје свој руковалац, који први прима необрађени изузетак, чува податке и тек онда завршава процес. На iOS-у се користи NSSetUncaughtExceptionHandler за NSException и Mach exception handler за сигнале.

Шта су fatal и non-fatal пад?

Fatal — апликација је завршена. Non-fatal (ухваћени изузетак) — програмер је ухватио изузетак кроз try-catch, али то може указивати на потенцијални проблем. Crashlytics разликује ове типове и омогућава филтрирање non-fatal одвојено како не би затрпавао контролну таблу.

Резиме

  • Crash — хитно заустављање апликације због необрађеног изузетка или фаталног сигнала
  • NullPointerException остаје најчешћи тип пада у мобилним апликацијама
  • Firebase Crashlytics — стандардни алат за прикупљање и анализу падова у продукцији
  • Анализа пада укључује читање stack trace-а, контекст уређаја и репродукцију у тест окружењу
  • Статичка анализа (Detekt, Lint) спречава део падова у фази компилације
  • Graceful degradation претвара потенцијалне падове у управљиве сценарије са резервним подацима
  • Мапинг фајлови су обавезни за деобфускацију stack trace-а у продукцијским верзијама

Развићемо мобилну апликацију под кључ

IT Sectr креира iOS и Android апликације за стартапе и предузећа од 2017. године. Саветоваћемо вас и предложити најбоље решење.

Разговарајте о пројекту

Прочитајте такође