Ghi tệp báo lỗi để xem những đối tượng 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 lỗi rò rỉ bộ nhớ hoặc hành vi phân bổ bộ nhớ dẫn đến tình trạng giật, treo và thậm chí là sự cố ứng dụng. Bạn nên ghi tệp báo lỗi sau một phiên đăng nhập kéo dài của người dùng, 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 nhẽ 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 tệp báo lỗi. 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 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 sẽ giải phóng bộ nhớ không dùng đến trở về vùng nhớ khối xếp. Cách Android tìm bộ nhớ không dùng đến liên tục được cải thiện, nhưng tại một thời điểm nào đó trên tất cả các phiên bản Android, hệ thống phải tạm dừng mã của bạn trong một khoảng thời gian ngắn. Hầu hết thời gian, các khoảng tạm dừng này đều không đáng chú ý. 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 ứ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 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: chạy "ứng dụng" ở 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:
Danh sách lớp 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.
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 vùng nhớ khối xếp để lọc theo một số vùng nhớ khối xếp nhất định:
- App heap (default) (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ớ.
- Image heap (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 (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 để lọc theo các nhóm lớp:
- All classes (default) (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.
- Show activity/fragment leaks (Hiện lỗi rò rỉ hoạt động/mảnh): Hiện các lớp gây ra lỗi 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 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ỉ hiện cho Android 7.0 trở lên.
- Shallow Size (Kích thước đối tượng): Kích thước của thực thể này trong bộ nhớ Java.
- 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
và References (Trường và 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 loại dữ liệu nguyên thuỷ
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.
- Fields (Trường): Hiện tất cả các trường trong thực thể này.
- References (Tham chiếu): Hiện mọi thông tin tham chiếu đến đối tượng được đánh dấu trong thẻ Instance (Thực thể).
Phát hiện bitmap trùng lặp
Bạn cũng có thể phát hiện bitmap dư 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 bitmap này:
- Mở thẻ Trình phân tích trong Android Studio
- 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 nút ghi để chụp nhanh trạng thái bộ nhớ hiện tại của ứng dụng.
- Quét kết quả phân tích để tìm tam giác cảnh báo màu vàng ⚠️. Android Studio dùng tam giác này để gắn cờ các bitmap trùng lặp đang được lưu trữ nhiều lần.
- Ngoài ra, hãy chuyển đến tiêu đề trình phân tích, chọn Filter by: (Lọc theo:) rồi chọn chế độ cài đặt Duplicate Bitmaps (Bitmap trùng lặp).
- 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 bị trùng lặp.
- Sử dụng thông tin xác nhận trực quan đó để theo dõi logic tải dư thừa trong mã của bạn và triển khai chiến lược lưu vào bộ nhớ đệm tốt hơn.
Tìm lỗi rò rỉ bộ nhớ
Để nhanh chóng lọc theo các lớp có thể liên quan đến 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/mảnh). Android Studio
cho thấy các lớp mà Android Studio cho rằng chỉ báo lỗi rò rỉ bộ nhớ cho
Activity và
Fragment thực thể 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 danh sách lớp và thực thể để 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 nguyên nhân bất kỳ trong số sau:
- Các tham chiếu tồn tại lâu dài đến
ActivityhoặcContextcó thể làm rò rỉ biểu đồ thành phần Compose được lưu trữ (chẳng hạn nhưComposeViewvà các thành phần con có thể kết hợp). - Rò rỉ các đối tượng Trạng thái Jetpack Compose (
MutableState), trình giữ trạng thái hoặc lambda thu thậpContext. - Quên dọn dẹp trình nghe hoặc trình quan sát trong khối
onDisposecủa aDisposableEffect. - Các lớp không tĩnh bên trong (chẳng hạn như
Runnable) có thể duy trì mộtActivitythực thể. - 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 lỗi rò rỉ bộ nhớ tiềm ẩn, hãy sử dụng các thẻ Fields (Trường) và References (Tham chiếu) trong Instance Details (Thông tin chi tiết về 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, lỗi rò rỉ càng nhỏ thì bạn càng cần chạy ứng dụng lâu hơn để thấy được lỗi đó.
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
làm rò rỉ
Activity(và do đó là cây giao diện người dùng Compose được lưu trữ và các cây trạng thái được liên kết) nếu ứng dụng của bạn giữ một tham chiếu đếnActivityhoặcContextbên trong các hoạt động không đồng bộ hoặc trình 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 của bạn.
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
từ thẻ Past Recordings (Bản ghi trước đây) trong trình phân tích. 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ó trong thư mục {android_sdk}/platform-tools/. Chạy lệnh hprof-conv với 2 đối số: tên tệp .hprof gốc 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