Crash ứng dụng: nó là gì, nguyên nhân đóng đột ngột và phương pháp phát hiện

Tác giả: IT Sectr Đã đăng: 2026-07-27 Thời gian đọc: 7 phút

Crash ứng dụng — sự kết thúc bất thường khi chương trình ngừng phản hồi và đóng lại. Trong phát triển di động, crash là nguồn chính của các đánh giá tiêu cực và giảm xếp hạng. Theo Firebase (2024), người dùng xóa ứng dụng sau một hoặc hai lần crash trong 53% trường hợp. Mỗi lần crash làm giảm tỷ lệ giữ chân 3–5%. Các hệ thống giám sát như Crashlytics và Sentry giúp nhanh chóng tìm và sửa nguyên nhân crash trước khi chúng ảnh hưởng đến nhiều người dùng.

Những điểm chính

  • Crash — ứng dụng kết thúc đột ngột do lỗi runtime không được xử lý
  • Nguyên nhân chính — NullPointerException, OutOfMemoryError, IndexOutOfBounds, ANR trong Android
  • Crashlytics — tiêu chuẩn giám sát crash với thu thập stack trace tự động và phân nhóm
  • Ngoại lệ runtime — ngoại lệ mà trình biên dịch không kiểm tra, chúng chỉ xuất hiện tại runtime
  • Chiến lược phòng ngừa — kiểu dữ liệu chặt chẽ, ràng buộc tùy chọn, xử lý lỗi và kiểm thử

Crash ứng dụng là gì

Crash — sự kết thúc bất ngờ của chương trình do một tình huống ngoại lệ mà mã không xử lý được. Trong hệ điều hành di động, crash dẫn đến việc đóng ứng dụng ngay lập tức và hiển thị màn hình “Ứng dụng đã dừng” hoặc quay lại màn hình chính.

Crash được chia thành hai lớp lớn. Lỗi đã xử lý — khối try/catch bắt ngoại lệ, ứng dụng tiếp tục chạy, có thể mất một số chức năng. Crash chưa xử lý — ngoại lệ lan lên đến cấp độ hệ điều hành và hệ thống kết thúc tiến trình. Loại thứ hai đặc biệt nguy hiểm vì người dùng không thể lưu dữ liệu.

Một hệ thống với hai triệu người dùng và tỷ lệ crash 0,1% mất 2.000 người dùng ở mỗi bản phát hành. Theo Google Play Console (2024), các ứng dụng có tỷ lệ crash trên 1,5% bị loại khỏi đề xuất và mất tới 30% lưu lượng truy cập tự nhiên.

Nguyên nhân chính gây crash trong ứng dụng di động

NullPointerException (NPE) — vua của các crash trong Java/Kotlin. Cố gắng gọi phương thức trên một đối tượng null. Trong Kotlin, NPE ít phổ biến hơn nhờ tính năng null safety, nhưng vẫn có thể xảy ra khi sử dụng toán tử !! hoặc tương tác với mã Java. Google (2024) ước tính NPE chiếm 25% tổng số crash ứng dụng Android.

IndexOutOfBoundsException — truy cập phần tử danh sách với chỉ mục không tồn tại. Nguyên nhân phổ biến: dữ liệu đến từ máy chủ ở định dạng không mong đợi và giao diện cố gắng hiển thị vị trí không tồn tại. Giải pháp — luôn kiểm tra kích thước bộ sưu tập trước khi truy cập theo chỉ mục.

ANR (Application Not Responding) — vấn đề đặc thù của Android. Luồng giao diện người dùng bị chặn hơn 5 giây. Nguyên nhân chính: yêu cầu mạng trên luồng chính, tính toán nặng, đồng bộ cơ sở dữ liệu. StrictMode trong Android giúp phát hiện chặn luồng giao diện trong quá trình phát triển.

OutOfMemoryError (OOM) — ứng dụng vượt quá giới hạn bộ nhớ. Trên thiết bị di động có 2–4 GB RAM, OOM là vấn đề phổ biến khi làm việc với hình ảnh lớn hoặc danh sách vô hạn không phân trang. Giải pháp — Glide/Coil để tải hình ảnh, LruCache để lưu cache, ViewHolder trong RecyclerView.

Ngoại lệ runtime và lỗi nghiêm trọng

Ngoại lệ runtime — lỗi mà trình biên dịch không kiểm tra tại thời điểm xây dựng. Chúng chỉ xuất hiện khi mã chạy trên một thiết bị cụ thể với dữ liệu cụ thể. Trong Java, đây là RuntimeException và các lớp con của nó: NullPointerException, IllegalArgumentException, ArithmeticException.

Lỗi nghiêm trọng (FATAL) — không phải runtime, mà là lỗi hệ thống. Signal 11 (SIGSEGV) — vi phạm phân đoạn bộ nhớ trong mã native. Signal 6 (SIGABRT) — kết thúc bất thường do chính ứng dụng gây ra qua abort(). Những crash này khó chẩn đoán vì stack trace thường không hiển thị ngữ cảnh rõ ràng.

Trong iOS, nguyên nhân chính là NSInvalidArgumentException (nil bất ngờ trong tham số) và EXC_BAD_ACCESS (truy cập bộ nhớ đã giải phóng). Swift đã giảm số lượng crash so với Objective-C, nhưng lỗi trong runtime ObjC và thư viện C vẫn gây ra crash.

Giám sát và thu thập nhật ký crash

Firebase Crashlytics — tiêu chuẩn cho ứng dụng di động. Tự động thu thập stack trace, thêm nhật ký, ID người dùng và siêu dữ liệu thiết bị. Phân nhóm crash theo chữ ký (lớp lỗi + dòng). Cảnh báo thời gian thực — thông báo khi tỷ lệ crash vượt quá ngưỡng đã đặt (ví dụ: >0,1% mỗi giờ).

Sentry — một giải pháp thay thế với khả năng linh hoạt hơn. Cho phép tạo ngữ cảnh tùy chỉnh, thêm breadcrumb (sự kiện trước đó), cấu hình bộ lọc trong ứng dụng để loại trừ các lỗi không quan trọng. Source maps cho Kotlin và Swift cho phép xem mã nguồn thay vì tên bị làm rối.

Các phương pháp hay nhất cho nhật ký: gửi siêu dữ liệu chính trước khi thực hiện thao tác nguy hiểm — nhờ đó nhật ký sẽ hiển thị người dùng đang làm gì trước khi crash. Thêm khóa tùy chỉnh (số phiên bản API, màn hình cuối cùng, kích thước dữ liệu đầu vào). Điều này biến stack trace vô dụng thành thông tin có thể hành động.

Ví dụ: thiết lập Crashlytics trong 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)
        }
    }
}

Chiến lược phòng ngừa crash

Ràng buộc tùy chọn và null safety — trong Kotlin sử dụng `?` cho kiểu nullable, `let` và `?:` để xử lý null an toàn. Trong Swift — optionals và guard let. Kotlin hiện đại (2024) đã thêm chú thích Contract: `@ContractsDsl` cho phép khai báo rằng một hàm không trả về null và trình biên dịch kiểm tra điều đó.

Xử lý lỗi mạng — mỗi yêu cầu mạng phải xử lý timeout, lỗi phân tích và lỗi máy chủ. Retrofit với kiểu Result — một lớp sealed đảm bảo lỗi sẽ được xử lý. Phong cách không ngoại lệ: thay vì try/catch, sử dụng Result sealed để xử lý rõ ràng thành công và lỗi.

Cờ tính năng — tắt chức năng có vấn đề từ xa mà không cần phát hành phiên bản mới. Nếu một thao tác máy chủ gây crash trên thiết bị cũ, cờ sẽ tắt nó cho nhóm đó. Firebase Remote Config cho phép thay đổi hành vi ứng dụng mà không cần xuất bản lên cửa hàng.

Triển khai dần dần — phát hành phiên bản mới cho 5% người dùng và theo dõi tỷ lệ crash. Nếu tỷ lệ duy trì dưới mục tiêu (thường <0,1%), mở rộng lên 25%, sau đó 50%, sau đó 100%. Google Play ConsoleApp Store Connect hỗ trợ triển khai theo giai đoạn để tự động dừng khi vượt ngưỡng.

Kế hoạch hành động khi phát hiện lỗi

Bước 1: Phân loại — xác định mức độ nghiêm trọng: Nghiêm trọng (crash ở >1% người dùng), Cao (0,1–1%), Trung bình (<0,1%). Với crash nghiêm trọng — phản hồi ngay lập tức. Với các trường hợp khác — quy trình sửa lỗi tiêu chuẩn trong sprint hiện tại. Google Play Console tự động phân loại crash theo số lượng người dùng bị ảnh hưởng.

Bước 2: Phân tích stack trace — mở nhật ký trong Crashlytics, xem vị trí crash chính xác. Kiểm tra khóa tùy chỉnh: màn hình nào, dữ liệu nào, phiên bản hệ điều hành. Liên hệ với bản triển khai gần nhất — thường crash do thay đổi mã gần đây ảnh hưởng đến kịch bản sử dụng không mong đợi.

Bước 3: Tái tạo — thử tái tạo crash trên thiết bị hoặc trình giả lập với tham số tương tự. Nếu không thành công, kiểm tra nhật ký crash theo mẫu: model cụ thể (Samsung A10), phiên bản Android (API < 26), ngôn ngữ. Giải pháp — thêm điều kiện phòng vệ bao phủ kịch bản.

Bước 4: Sửa lỗi và giám sát — phát hành bản vá ưu tiên. Sau khi phát hành, đảm bảo tỷ lệ crash cho loại này giảm xuống không. Viết kiểm thử hồi quy bao phủ kịch bản crash. Nếu không có kiểm thử, cùng một lỗi có thể quay lại trong lần tái cấu trúc tiếp theo.

Câu hỏi thường gặp

Tỷ lệ crash nào được coi là bình thường?

Tỷ lệ crash bình thường — dưới 0,1% cho các bản phát hành production. Google Play khuyến nghị giữ tỷ lệ crash dưới 1,5%, nhưng các ứng dụng hàng đầu (YouTube, Instagram) duy trì 0,01–0,05%. Đối với bản phát hành có chức năng mới, cho phép tăng tạm thời lên 0,5% với điều kiện giảm sau khi có bản vá.

Crash khác ANR như thế nào?

Crash — ứng dụng kết thúc bất thường. ANR (Application Not Responding) — ứng dụng bị treo hơn 5 giây nhưng không bị đóng bắt buộc. Người dùng thấy hộp thoại “Ứng dụng không phản hồi” và có thể đợi hoặc đóng. Vấn đề ANR không kém nghiêm trọng hơn crash và cũng ảnh hưởng đến xếp hạng cửa hàng.

Tại sao crash có thể không tái tạo trên tất cả thiết bị?

Các thiết bị khác nhau có phiên bản hệ điều hành, dung lượng bộ nhớ, phiên bản thư viện và thậm chí bộ xử lý khác nhau. Ví dụ: crash trên Android 6 (API 23) do thiếu quyền runtime có thể không tái tạo trên Android 12. Phân tích nhật ký crash theo bộ lọc: phiên bản hệ điều hành, model thiết bị, dung lượng RAM. Điều này sẽ chỉ ra tính đặc thù của vấn đề.

Làm thế nào để tìm nguyên nhân crash nếu stack trace không cung cấp thông tin?

Thêm breadcrumb tùy chỉnh trong Crashlytics: ghi lại các sự kiện chính trước khi thực hiện thao tác. Nếu crash xảy ra ở bước 3 của quy trình hướng dẫn, điều này cho thấy vấn đề ở một màn hình cụ thể. Ký hiệu gỡ lỗi (dSYM, ProGuard mapping) — luôn tải chúng lên Crashlytics để thấy tên hàm thực thay vì tên bị làm rối.

Có nên crash ứng dụng khi gặp lỗi không nghiêm trọng?

Trong môi trường production — không bao giờ. Crash chưa xử lý làm xấu trải nghiệm người dùng. Sử dụng try/catch với ghi nhật ký lỗi. Trong chế độ gỡ lỗi, crash có thể chấp nhận được để phản hồi nhanh cho nhà phát triển. Assertions — để kiểm tra các bất biến không bao giờ được vi phạm, nhưng chỉ trong bản dựng gỡ lỗi.

Tổng kết

  • Crash — kết thúc bất thường của ứng dụng dẫn đến mất người dùng và giảm xếp hạng cửa hàng
  • NullPointerException — nguyên nhân phổ biến nhất gây crash trong ứng dụng di động (25% tổng số crash)
  • ANR và OOM — vấn đề nghiêm trọng đặc thù của Android cần giám sát và phòng ngừa riêng
  • Crashlytics và Sentry — công cụ chính thu thập stack trace với phân nhóm và cảnh báo thời gian thực
  • Xử lý lỗi — ràng buộc tùy chọn, kiểu Result sealed và kiểm tra phòng vệ ngăn chặn hầu hết crash
  • Cờ tính năng và triển khai dần dần — giảm tác động của lỗi lên người dùng, cho phép hoàn nguyên mã có vấn đề
  • Sau khi sửa crash — kiểm thử hồi quy bắt buộc để ngăn tái diễn vấn đề

Chúng tôi sẽ phát triển ứng dụng di động chìa khóa trao tay

IT Sectr tạo các ứng dụng iOS và Android cho các công ty khởi nghiệp và doanh nghiệp từ năm 2017. Chúng tôi sẽ tư vấn và đề xuất giải pháp tốt nhất cho bạn.

Thảo luận dự án

Đọc thêm