Ghi tệp báo lỗi

Ghi tệp báo lỗi để xem những đối tượng nào trong ứng dụng đang dùng hết bộ nhớ tại thời điểm ghi và xác định tình trạng rò rỉ bộ nhớ hoặc hành vi phân bổ bộ nhớ dẫn đến tình trạng gián đoạn, treo và thậm chí là sự cố ứng dụng. Việc thu thập tệp báo lỗi đặc biệt hữu ích sau một phiên đăng nhập kéo dài của người dùng, khi tệp này có thể cho thấy các đối tượng vẫn còn trong bộ nhớ mà đáng nhẽ không nên ở đó nữa.

Trang này mô tả công cụ mà Android Studio cung cấp để thu thập và phân tích tệp báo lỗi khối xếp. Ngoài ra, bạn có thể kiểm tra bộ nhớ của ứng dụng qua dòng lệnh bằng dumpsys cũng như xem các sự kiện thu gom rác (GC) trong Logcat.

Tại sao bạn nên phân tích bộ nhớ ứng dụng

Android cung cấp một môi trường bộ nhớ được quản lý – khi nhận thấy ứng dụng của bạn không còn sử dụng một số đối tượng, trình thu gom rác (garbage collector) sẽ giải phóng bộ nhớ không dùng đến trở về vùng nhớ khối xếp. Tuy Android liên tục cải tiến cách tìm bộ nhớ không dùng đến, nhưng đến một thời điểm nào đó trên mọi phiên bản Android, hệ thống sẽ phải tạm dừng mã của bạn trong giây lát. Trong hầu hết trường hợp, bạn sẽ không nhận thấy việc tạm dừng. Tuy nhiên, nếu ứng dụng của bạn phân bổ bộ nhớ nhanh hơn tốc độ hệ thống thu thập bộ nhớ, thì ứng dụng của bạn có thể bị gián đoạn trong khi trình thu gom giải phóng đủ bộ nhớ để đáp ứng mức phân bổ. Tình trạng trễ này có thể khiến ứng dụng của bạn bỏ qua khung hình cũng như làm chậm khung hình.

Ngay cả khi ứng dụng của bạn không bị chậm lại, nếu bị rò rỉ bộ nhớ, thì ứng dụng vẫn có thể giữ lại bộ nhớ đó ngay cả khi đang ở chế độ nền. Tình trạng này có thể làm giảm hiệu suất của bộ nhớ còn lại trong hệ thống do các sự kiện buộc thu thập rác không cần thiết. Cuối cùng, hệ thống buộc phải đóng quy trình ứng dụng để lấy lại bộ nhớ. Sau đó, khi người dùng trở lại ứng dụng của bạn, quy trình của ứng dụng phải khởi động lại hoàn toàn.

Để biết thông tin về các phương pháp lập trình có thể làm giảm mức sử dụng bộ nhớ của ứng dụng, hãy đọc nội dung [Quản lý bộ nhớ của ứng dụng]memory.

Tổng quan về tệp báo lỗi

Để ghi tệp báo lỗi, hãy chọn tác vụ Analyze Memory Usage (Heap Dump) (Phân tích mức sử dụng bộ nhớ (Tệp báo lỗi)) (sử dụng Profiler: run 'app' as debuggable (complete data) (Trình phân tích tài nguyên: chạy "ứng dụng" dưới dạng có thể gỡ lỗi (dữ liệu hoàn chỉnh)) để ghi tệp báo lỗi. Trong khi kết xuất vùng nhớ khối xếp, mức sử dụng bộ nhớ Java có thể tạm thời tăng lên. Hiện tượng này là bình thường vì tệp báo lỗi và ứng dụng của bạn diễn ra trong cùng một quy trình với ứng dụng, đồng thời cần có một lượng bộ nhớ để thu thập dữ liệu. Sau khi ghi tệp báo lỗi, bạn sẽ thấy những thông tin sau:

Chế độ xem tệp báo lỗi trong Trình phân tích tài nguyên của Android Studio.

Danh sách lớp học cho biết những thông tin sau:

  • Allocations (Phân bổ): Số lượt phân bổ trong vùng nhớ khối xếp.
  • Native Size (Kích thước gốc): Tổng dung lượng bộ nhớ gốc mà loại đối tượng này sử dụng (tính bằng byte). Bạn sẽ thấy bộ nhớ ở đây cho một số đối tượng được phân bổ trong Java vì Android sử dụng bộ nhớ gốc cho một số lớp khung (chẳng hạn như Bitmap).

  • Shallow Size (Kích thước nông): Tổng dung lượng bộ nhớ Java mà loại đối tượng này sử dụng (tính bằng byte).

  • Retained Size (Kích thước được giữ lại): Tổng kích thước bộ nhớ được giữ lại do tất cả các thực thể của lớp này (tính bằng byte).

Sử dụng trình đơn vùng nhớ khối xếp để lọc ra một số vùng nhớ khối xếp nhất định:

  • App heap (Vùng nhớ khối xếp ứng dụng) (mặc định): Vùng nhớ khối xếp chính nơi ứng dụng của bạn phân bổ bộ nhớ.
  • Vùng nhớ khối xếp hình ảnh: Hình ảnh khởi động của hệ thống, chứa các lớp được tải trước trong thời gian khởi động. Mức phân bổ tại đây không bao giờ di chuyển hoặc biến mất.
  • Zygote heap (bộ nhớ khối xếp zygote): Vùng nhớ khối xếp dạng ngầm sao chép (copy-on-write) nơi quy trình ứng dụng được phát triển nhánh qua hệ thống Android.

Sử dụng trình đơn thả xuống về cách sắp xếp để chọn cách sắp xếp các lượt phân bổ:

  • Arrange by class (default) (Sắp xếp theo lớp (mặc định)): Nhóm tất cả lượt phân bổ dựa trên tên lớp.
  • Arrange by package (Sắp xếp theo gói): Nhóm tất cả lượt phân bổ dựa trên tên gói.

Sử dụng trình đơn thả xuống của lớp để lọc theo nhóm lớp:

  • Tất cả các lớp (mặc định): Cho thấy tất cả các lớp, bao gồm cả các lớp trong thư viện và phần phụ thuộc.
  • Show activity/fragment leaks (Hiện hoạt động/mảnh bị rò rỉ): Hiện các lớp đang gây ra rò rỉ bộ nhớ.
  • Show project classes (Hiện các lớp của dự án): chỉ hiện các lớp do dự án của bạn xác định.

Nhấp vào tên lớp để mở ngăn Instance (Thực thể). Mỗi thực thể được liệt kê lại có những thông tin sau đây:

  • Depth (Chiều sâu): Số bước nhảy ngắn nhất từ gốc GC bất kỳ đến thực thể đã chọn.
  • Native Size (Kích thước gốc): Kích thước của thực thể này trong bộ nhớ gốc. Cột này chỉ xuất hiện trên Android 7.0 trở lên.
  • Shallow Size (Kích thước của đối tượng): Kích thước của thực thể này trong bộ nhớ Java.
  • Retained Size (Kích thước được giữ lại): Kích thước của bộ nhớ mà thực thể này chiếm ưu thế (theo sơ đồ ưu thế (dominator tree)).

Nhấp vào một thực thể để hiện Instance Details (Thông tin chi tiết về thực thể), bao gồm cả Fields (Trường) và References (Tham chiếu). Các loại trường và tham chiếu phổ biến là các loại có cấu trúc , mảng , và các kiểu dữ liệu gốc trong Java. Nhấp chuột phải vào một trường hoặc tệp đối chiếu để chuyển đến thực thể hoặc dòng liên kết trong mã nguồn.

  • Trường: Cho thấy tất cả các trường trong thực thể này.
  • References (Tham chiếu): Cho thấy mọi thông tin tham chiếu đến đối tượng được làm nổi bật trong thẻ Instance (Thực thể).
Chế độ xem Instances (Thực thể), Fields (Trường) và References (Tham chiếu) trong cửa sổ công cụ Heap Dump (tệp báo lỗi).

Phát hiện bitmap trùng lặp

Bạn cũng có thể phát hiện bitmap thừa trong chế độ xem tệp báo lỗi bắt đầu từ Android Studio Narwhal 4.

Sau đây là cách tìm các ứng dụng này:

  1. Mở thẻ Trình phân tích tài nguyên trong Android Studio
  2. Nhấp vào Heap Dump (tệp báo lỗi) (hoặc Analyze Memory Usage (Phân tích mức sử dụng bộ nhớ)) rồi nhấp vào biểu tượng ghi để chụp nhanh trạng thái bộ nhớ hiện tại của ứng dụng.
  3. Quét kết quả phân tích để tìm biểu tượng tam giác cảnh báo màu vàng ⚠️ mà Android Studio dùng để gắn cờ các bitmap trùng lặp được lưu trữ nhiều lần.
    • Ngoài ra, hãy chuyển đến tiêu đề trình phân tích tài nguyên, chọn Filter by: (Lọc theo:) rồi chọn chế độ cài đặt Duplicate Bitmaps (Bitmap trùng lặp).
  4. Nhấp vào bất kỳ mục nào được gắn cờ để mở ngăn Bitmap Preview (Xem trước bitmap), cho phép bạn xem chính xác hình ảnh nào là hình ảnh vi phạm nhiều lần.
  5. Hãy sử dụng thông tin xác nhận trực quan đó để theo dõi logic tải thừa trong mã của bạn và triển khai chiến lược lưu vào bộ nhớ đệm hiệu quả hơn.
Tìm bitmap trùng lặp bằng biểu tượng cảnh báo màu vàng ⚠️.

Tìm lỗi rò rỉ bộ nhớ

Để nhanh chóng lọc ra các lớp có thể liên quan đến rò rỉ bộ nhớ, hãy mở trình đơn thả xuống của lớp rồi chọn Show activity/fragment leaks (Hiện hoạt động/mảnh bị rò rỉ). Android Studio cho thấy các lớp mà công cụ này cho rằng có thể chỉ báo lỗi rò rỉ bộ nhớ cho các thực thể Activity và Fragment trong ứng dụng của bạn.

Để tìm lỗi rò rỉ bộ nhớ theo cách thủ công hơn, hãy duyệt xem danh sách lớp và thực thể để tìm các đối tượng có Retained Size (kích thước được giữ lại) lớn. Tìm lỗi rò rỉ bộ nhớ do nguyên nhân bất kỳ trong số sau:

  • Các tệp đối chiếu tồn tại lâu dài với Activity hoặc Context có thể làm rò rỉ biểu đồ thành phần Compose được lưu trữ (chẳng hạn như ComposeView và các thành phần phụ của nó).
  • Rò rỉ đối tượng Trạng thái Jetpack Compose (MutableState), phần tử giữ trạng thái hoặc lambda thu thập Context.
  • Quên dọn dẹp trình nghe hoặc đối tượng tiếp nhận dữ liệu trong khối onDispose của DisposableEffect.
  • Các lớp không tĩnh bên trong (chẳng hạn như Runnable) có thể duy trì một thực thể Activity.
  • Bộ nhớ đệm duy trì các đối tượng lâu hơn mức cần thiết.

Khi bạn tìm thấy các trường hợp có thể gây rò rỉ bộ nhớ, hãy sử dụng thẻ Fields (Trường) và References (Tham chiếu) trong Instance Details (Chi tiết thực thể) để chuyển đến thực thể hoặc dòng mã nguồn mà bạn quan tâm.

Kích hoạt lỗi rò rỉ bộ nhớ để kiểm thử

Để phân tích mức sử dụng bộ nhớ, bạn nên tạo áp lực cho mã nguồn ứng dụng và buộc rò rỉ bộ nhớ. Có một cách để tìm ra lỗi rò rỉ bộ nhớ trong ứng dụng là cho ứng dụng chạy một lúc trước khi kiểm tra vùng nhớ khối xếp. Các lỗi rò rỉ có thể dần lộ ra trên quá trình phân bổ trong vùng nhớ khối xếp. Tuy nhiên, rò rỉ càng ít thì bạn cần chạy ứng dụng càng lâu để thấy được nơi rò rỉ.

Bạn cũng có thể kích hoạt sự cố rò rỉ bộ nhớ theo một trong các cách sau:

  • Liên tục xoay thiết bị từ chế độ dọc sang chế độ ngang rồi ngược lại trong khi ở nhiều trạng thái hoạt động. Việc xoay thiết bị thường có thể khiến ứng dụng rò rỉ Activity (và do đó, cây giao diện người dùng Compose được lưu trữ và các cây trạng thái liên quan) nếu ứng dụng của bạn giữ tham chiếu đến Activity hoặc Context bên trong các thao tác không đồng bộ hoặc phần tử giữ trạng thái.
  • Chuyển đổi giữa ứng dụng của bạn với một ứng dụng khác khi ở nhiều trạng thái hoạt động. Ví dụ: chuyển đến màn hình chính, sau đó quay lại ứng dụng.

Xuất và nhập bản ghi tệp báo lỗi

Bạn có thể xuất và nhập tệp báo lỗi khối xếp từ thẻ Bản ghi trước đây trong trình phân tích tài nguyên. Android Studio lưu bản ghi dưới dạng tệp .hprof.

Ngoài ra, để sử dụng một trình phân tích tệp .hprof khác (chẳng hạn như jhat), bạn cần chuyển đổi tệp .hprof từ định dạng Android sang định dạng tệp .hprof Java SE. Để chuyển đổi định dạng tệp, hãy sử dụng công cụ hprof-conv được cung cấp trong thư mục {android_sdk}/platform-tools/. Chạy lệnh hprof-conv với hai đối số: tên tệp .hprof ban đầu và vị trí để ghi tệp .hprof đã chuyển đổi, bao gồm cả tên tệp .hprof mới. Ví dụ:

hprof-conv heap-original.hprof heap-converted.hprof

Tài nguyên khác