Ghi tệp báo lỗi

Ghi lại tệp báo lỗi để xem những đối tượng nào trong ứng dụng của bạn đ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, bị treo và thậm chí gặp sự cố cho ứng dụng. Việc lấy tệp báo lỗi sau một phiên hoạt động kéo dài của người dùng sẽ đặc biệt hữu ích, vì khi đó, tệp báo lỗi có thể cho thấy các đối tượng vẫn còn trong bộ nhớ mà đáng lẽ không nên ở đó nữa.

Trang này mô tả các công cụ mà Android Studio cung cấp để thu thập và phân tích kết xuất heap. 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 thập 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 Android xác định rằng ứ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 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 quay 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.

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

Để ghi lại 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 đầy đủ))) để ghi lại 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 Heap Dump trong Trình phân tích tài nguyên của Android Studio.

Danh sách lớp học cho thấy 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 đối tượ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 giữ lại): Tổng dung lượng 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 nhóm để lọc theo một số nhóm nhất định:

  • 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 sẽ không bao giờ di chuyển hoặc biến mất.
  • Vùng 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 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 lớp học để lọc theo nhóm lớp học:

  • Tất cả các lớp (mặc định): Hiển thị tất cả các lớp, bao gồm cả các lớp từ thư viện và phần phụ thuộc.
  • Hiện các hoạt động/mảnh bị rò rỉ: Hiện các lớp gây ra tình trạng rò rỉ bộ nhớ.
  • Show project classes (Hiện các lớp 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 phiên bản được liệt kê đều có những thông tin sau:

  • 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 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ế).

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 (Tài liệu tham khảo). Các trường và loại 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 nguyên gốc trong Java. Nhấp chuột phải vào một trường hoặc tham chiếu để chuyển đến thực thể hoặc dòng được liên kết trong mã nguồn.

  • Trường: Hiển thị tất cả các trường trong phiên bản này.
  • References (Tham chiếu): Cho biết 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ể).
Các khung hiển thị Instances (Các thực thể), Fields (Các trường) và References (Các tham chiếu) trong cửa sổ công cụ Heap Dump (Kết xuất heap).

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

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

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

  • Các tham chiếu tồn tại lâu dài đến Activity hoặc Context có thể 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 kết hợp phụ của thành phần này).
  • Rò rỉ các đối tượng Trạng thái Jetpack Compose (MutableState), phần tử giữ trạng thái hoặc lambda chụp Context.
  • Quên dọn dẹp các 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 phát hiện 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 (Giá trị tham chiếu) trong Instance Details (Thông tin chi tiết về phiên bản) để chuyển đến phiên bản hoặc dòng mã nguồn mà bạn quan tâm.

Kích hoạt 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ớ. 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 kết) nếu ứng dụng của bạn tham chiếu đến Activity hoặc Context trong các thao tác không đồng bộ hoặc các trình giữ trạng thái.
  • Chuyển đổi giữa ứng dụng của bạn và 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 của bạn.

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

Bạn có thể xuất và nhập tệp báo lỗi bộ nhớ 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 dùng công cụ hprof-conv có 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