Tài liệu này giả định rằng bạn đã làm theo hướng dẫn về các phương pháp hay nhất dành cho ứng dụng Android trong phần quản lý bộ nhớ, chẳng hạn như Quản lý bộ nhớ của ứng dụng.
Giới thiệu
Rò rỉ bộ nhớ là một loại rò rỉ tài nguyên xảy ra khi máy tính sẽ không giải phóng bộ nhớ được phân bổ không còn cần thiết nữa. Rò rỉ có thể khiến ứng dụng yêu cầu hệ điều hành nhiều bộ nhớ hơn không khả dụng và do đó gây ra sự cố cho ứng dụng. Một số phương pháp không phù hợp có thể gây rò rỉ bộ nhớ trong ứng dụng Android, chẳng hạn như việc xử lý không đúng cách hoặc không huỷ đăng ký trình nghe khi không còn cần thiết nữa.
Tài liệu này cung cấp cho bạn một số phương pháp hay nhất để giúp ngăn chặn, phát hiện và khắc phục lỗi rò rỉ bộ nhớ trong mã. Nếu bạn đã thử các phương pháp trong tài liệu và nghi ngờ có sự cố rò rỉ bộ nhớ trong SDK của chúng tôi, hãy xem Cách báo cáo vấn đề liên quan đến Google SDK.
Trước khi bạn liên hệ với nhóm hỗ trợ
Trước khi bạn báo cáo sự cố rò rỉ bộ nhớ cho nhóm hỗ trợ Google, hãy làm theo phương pháp hay nhất cùng với các bước gỡ lỗi được cung cấp trong tài liệu này để đảm bảo không có lỗi trong mã của bạn. Các bước này có thể giải quyết được vấn đề của bạn và nếu mà không có, chúng tạo ra thông tin mà nhóm hỗ trợ Google cần để trợ giúp bạn.
Tránh rò rỉ bộ nhớ
Hãy làm theo các phương pháp hay nhất sau để tránh một số nguyên nhân phổ biến nhất gây ra rò rỉ bộ nhớ trong mã sử dụng Google SDK.
Các phương pháp hay nhất cho ứng dụng Android
Kiểm tra để đảm bảo bạn đã thực hiện tất cả những thao tác sau trong ứng dụng Android:
- Giải phóng tài nguyên không sử dụng.
- Huỷ đăng ký trình nghe khi không còn cần thiết nữa.
- Huỷ việc cần làm khi không cần thiết.
- Chuyển tiếp các phương thức vòng đời để giải phóng tài nguyên.
- Sử dụng các phiên bản SDK mới nhất
Để biết thông tin chi tiết cụ thể về từng phương pháp này, hãy xem các phần sau.
Giải phóng tài nguyên không dùng đến
Khi ứng dụng Android của bạn sử dụng một tài nguyên, hãy nhớ giải phóng tài nguyên đó dữ liệu đó không còn cần thiết nữa. Nếu không, tài nguyên sẽ tiếp tục chiếm bộ nhớ ngay cả sau khi ứng dụng của bạn hoàn tất. Để biết thêm thông tin, hãy xem Vòng đời hoạt động trong tài liệu Android.
Phát hành tệp tham chiếu GoogleMap cũ trong GeoSDK
Một sai lầm phổ biến là GoogleMap có thể gây ra sự cố rò rỉ bộ nhớ nếu sử dụng NavigationView hoặc MapView. GoogleMap có mối quan hệ 1-1 với NavigationView hoặc MapView mà từ đó đối tượng được truy xuất. Bạn phải đảm bảo rằng GoogleMap không được lưu vào bộ nhớ đệm hoặc rằng tham chiếu được huỷ bỏ khi NavigationView#onDestroy hoặc MapView#onDestroy được gọi. Nếu sử dụng NavigationSupportFragment, MapSupportFragment hoặc mảnh của riêng bạn gói các khung hiển thị này, thì tham chiếu phải được phát hành trong Fragment#onDestroyView.
class NavFragment : SupportNavigationFragment() {
var googleMap: GoogleMap?
override fun onCreateView(
inflater: LayoutInflater,
parent: ViewGroup?,
savedInstanceState: Bundle?,
): View {
super.onCreateView(inflater,parent,savedInstanceState)
getMapAsync{map -> googleMap = map}
}
override fun onDestroyView() {
googleMap = null
}
}
Huỷ đăng ký trình nghe khi không còn cần thiết
Khi ứng dụng Android của bạn đăng ký một trình nghe cho một sự kiện, chẳng hạn như một nút nhấp chuột hoặc thay đổi về trạng thái của khung hiển thị, hãy nhớ huỷ đăng ký trình nghe khi ứng dụng không cần theo dõi sự kiện đó nữa. Nếu không, các trình nghe tiếp tục chiếm bộ nhớ ngay cả sau khi ứng dụng của bạn kết thúc với họ.
Ví dụ: giả sử ứng dụng của bạn sử dụng SDK điều hướng và ứng dụng gọi
trình nghe sau đây để theo dõi các sự kiện đến:
addArrivalListener
để theo dõi các sự kiện đến, phương thức này cũng sẽ gọi
removeArrivalListener
khi không cần theo dõi các sự kiện đến nữa.
var arrivalListener: Navigator.ArrivalListener? = null
fun registerNavigationListeners() {
arrivalListener =
Navigator.ArrivalListener {
...
}
navigator.addArrivalListener(arrivalListener)
}
override fun onDestroy() {
navView.onDestroy()
if (arrivalListener != null) {
navigator.removeArrivalListener(arrivalListener)
}
...
super.onDestroy()
}
Huỷ việc cần làm khi không cần
Khi một ứng dụng Android khởi động một tác vụ không đồng bộ, chẳng hạn như tải xuống hoặc yêu cầu mạng, hãy nhớ huỷ tác vụ khi hoàn thành. Nếu việc cần làm không bị huỷ mà vẫn tiếp tục chạy trong nền ngay cả sau khi ứng dụng đã hoàn tất với nó.
Để biết thêm thông tin về các phương pháp hay nhất, hãy xem Quản lý bộ nhớ của ứng dụng trong tài liệu Android.
Chuyển tiếp các phương thức vòng đời để giải phóng tài nguyên
Nếu ứng dụng của bạn sử dụng SDK Điều hướng hoặc Maps, hãy nhớ phát hành
bằng cách chuyển tiếp các phương thức vòng đời (xuất hiện ở dạng in đậm) đến navView
. Bạn có thể
thực hiện việc này bằng cách sử dụng NavigationView
trong SDK điều hướng hoặc MapView
trong Maps hoặc
SDK điều hướng. Bạn cũng có thể sử dụng SupportNavigationFragment
hoặc
SupportMapFragment
thay vì trực tiếp sử dụng NavigationView
và MapView
,
. Mảnh hỗ trợ xử lý việc chuyển tiếp vòng đời
.
class NavViewActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
...
navView = ...
navView.onCreate(savedInstanceState)
...
}
override fun onSaveInstanceState(savedInstanceState: Bundle) {
super.onSaveInstanceState(savedInstanceState)
navView.onSaveInstanceState(savedInstanceState)
}
override fun onTrimMemory(level: Int) {
super.onTrimMemory(level)
navView.onTrimMemory(level)
}
/* Same with
override fun onStart()
override fun onResume()
override fun onPause()
override fun onConfigurationChanged(...)
override fun onStop()
override fun onDestroy()
*/
}
Sử dụng phiên bản SDK mới nhất
Google SDK liên tục được cập nhật với các tính năng mới, bản sửa lỗi và hiệu suất. Hãy luôn cập nhật các SDK trong ứng dụng của bạn để nhận được những tính năng này bản sửa lỗi.
Gỡ lỗi rò rỉ bộ nhớ
Nếu bạn vẫn thấy bộ nhớ bị rò rỉ sau khi triển khai tất cả các các gợi ý trước đó trong tài liệu này, hãy làm theo quy trình này để gỡ lỗi.
Trước khi bắt đầu, bạn nên nắm rõ cách Android quản lý bộ nhớ. Để biết thông tin, hãy đọc Tổng quan về việc quản lý bộ nhớ.
Để gỡ lỗi rò rỉ bộ nhớ, hãy làm theo quy trình sau:
- Tái tạo vấn đề. Bạn cần phải thực hiện bước này để gỡ lỗi.
- Kiểm tra xem mức sử dụng bộ nhớ có dự kiến hay không. Kiểm tra để đảm bảo mức sử dụng tăng dường như bị rò rỉ không thực sự là bộ nhớ cần thiết để chạy ứng dụng của bạn.
- Gỡ lỗi ở cấp độ cao. Bạn có thể sử dụng một số tiện ích sử dụng để gỡ lỗi. 3 bộ công cụ tiêu chuẩn giúp gỡ lỗi các vấn đề về bộ nhớ trong Android: Android Studio, Perfetto và Cầu gỡ lỗi Android (adb) các tiện ích dòng lệnh.
- Kiểm tra mức sử dụng bộ nhớ của ứng dụng. Tải tệp báo lỗi và theo dõi quá trình phân bổ rồi phân tích.
- Khắc phục lỗi rò rỉ bộ nhớ.
Các phần sau đây trình bày chi tiết về các bước này.
Bước 1: Tạo lại vấn đề
Nếu bạn không thể tạo lại vấn đề, trước tiên hãy xem xét các tình huống có thể dẫn đến rò rỉ bộ nhớ. Đi thẳng vào việc nhìn vào Tệp báo lỗi có thể hoạt động nếu bạn biết sự cố đã được tạo lại. Tuy nhiên, nếu bạn chỉ nhận được một tệp báo lỗi khi khởi động ứng dụng hoặc tại một thời điểm ngẫu nhiên khác, thì có thể bạn chưa kích hoạt các điều kiện gây ra sự cố rò rỉ. Cân nhắc giải quyết nhiều tình huống khi cố gắng tạo lại vấn đề:
Những tính năng nào được kích hoạt?
Trình tự hành động cụ thể nào của người dùng gây ra sự cố rò rỉ?
- Bạn đã thử kích hoạt trình tự này nhiều lần chưa?
Ứng dụng đã trải qua những trạng thái nào trong vòng đời?
- Bạn đã thử lặp lại nhiều lần qua các trạng thái vòng đời khác nhau chưa?
Hãy đảm bảo rằng bạn có thể tạo lại vấn đề trong phiên bản SDK mới nhất. Chiến lược phát hành đĩa đơn từ phiên bản trước đó có thể đã được khắc phục.
Bước 2: Kiểm tra xem mức sử dụng bộ nhớ của ứng dụng có dự kiến hay không
Mọi tính năng đều cần thêm bộ nhớ. Khi gỡ lỗi các tình huống khác nhau, xem xét liệu đây có phải là mục đích sử dụng dự kiến hay không hoặc đó có thực sự là rò rỉ bộ nhớ. Ví dụ: đối với các tính năng hoặc tác vụ khác nhau của người dùng, hãy cân nhắc khả năng sau:
Có thể là tình trạng rò rỉ dữ liệu: Kích hoạt tình huống này thông qua nhiều lần lặp lại làm tăng mức sử dụng bộ nhớ theo thời gian.
Mức sử dụng bộ nhớ có thể theo dự kiến: Bộ nhớ sẽ được thu hồi sau tình huống đã dừng.
Mức sử dụng bộ nhớ có thể theo dự kiến: Mức sử dụng bộ nhớ tăng lên trong một khoảng thời gian rồi giảm dần. Điều này có thể là do một bộ nhớ đệm bị chặn hoặc nguyên nhân khác mức sử dụng bộ nhớ.
Nếu hành vi của ứng dụng có thể là mức sử dụng bộ nhớ dự kiến, thì vấn đề có thể là được xác định bằng cách quản lý bộ nhớ của ứng dụng. Để được trợ giúp, hãy xem Quản lý bộ nhớ của ứng dụng.
Bước 3: Gỡ lỗi ở cấp độ cao
Khi bạn khắc phục sự cố rò rỉ bộ nhớ, hãy bắt đầu từ mức cao, sau đó xem chi tiết khi bạn đã thu hẹp các khả năng. Hãy sử dụng một trong các cấp cao nhất sau đây để phân tích trước tiên nếu có sự rò rỉ dữ liệu theo thời gian:
Trình phân tích bộ nhớ trong Android Studio (Nên dùng)
Trình phân tích bộ nhớ trong Android Studio
Công cụ này cung cấp cho bạn một biểu đồ trực quan về mức sử dụng bộ nhớ. Tệp báo lỗi và tính năng theo dõi hoạt động phân bổ cũng có thể được kích hoạt từ cùng giao diện này. Chiến dịch này là đề xuất mặc định. Để biết thêm thông tin, hãy xem Trình phân tích bộ nhớ trong Android Studio.
Bộ đếm bộ nhớ Perfetto
Perfetto giúp bạn kiểm soát chính xác theo dõi một vài chỉ số và trình bày tất cả trong một biểu đồ duy nhất. Để thông tin khác, xem Bộ đếm bộ nhớ Perfetto.
Tiện ích dòng lệnh của cầu gỡ lỗi Android (adb)
Hầu hết những nội dung bạn có thể theo dõi bằng Perfetto cũng hoạt động dưới dạng adb
tiện ích dòng lệnh mà bạn có thể truy vấn trực tiếp. Một vài điều quan trọng
ví dụ như:
Meminfo giúp bạn xem thông tin chi tiết về bộ nhớ tại một thời điểm.
Procstats cung cấp một số số liệu thống kê tổng hợp quan trọng theo thời gian.
Một số liệu thống kê quan trọng cần xem xét ở đây là mức sử dụng bộ nhớ thực tế tối đa
(maxRSS) mà ứng dụng yêu cầu theo thời gian. MaxPSS có thể không chính xác bằng. Để
một cách để tăng độ chính xác, hãy xem
Cờ adb shell dumpsys procstats --help –start-testing
.
Theo dõi mức phân bổ
Tính năng theo dõi phân bổ giúp xác định dấu vết ngăn xếp nơi phân bổ bộ nhớ và nếu không được giải phóng. Bước này đặc biệt hữu ích khi theo dõi các rò rỉ trong mã gốc. Vì công cụ này xác định dấu vết ngăn xếp, nên đây có thể là một có nghĩa là nhanh chóng gỡ lỗi căn nguyên hoặc tìm ra cách tạo lại vấn đề. Để biết các bước sử dụng tính năng theo dõi phân bổ, hãy xem Gỡ lỗi bộ nhớ trong mã gốc bằng tính năng theo dõi phân bổ.
Bước 4: Kiểm tra mức sử dụng bộ nhớ của ứng dụng bằng tệp báo lỗi
Một cách để phát hiện sự cố rò rỉ bộ nhớ là lấy tệp báo lỗi của ứng dụng và sau đó kiểm tra xem nó có bị rò rỉ hay không. Tệp báo lỗi là ảnh chụp nhanh của tất cả các đối tượng trong bộ nhớ của ứng dụng. Dữ liệu này có thể được dùng để chẩn đoán lỗi rò rỉ bộ nhớ và các vấn đề các vấn đề liên quan đến bộ nhớ.
Android Studio có thể phát hiện các sự cố rò rỉ bộ nhớ mà GC không khắc phục được. Khi bạn chụp tệp báo lỗi, Android Studio sẽ kiểm tra xem có hoạt động hoặc mảnh nào hay không vẫn có thể truy cập được nhưng đã bị huỷ bỏ.
Để biết chi tiết, hãy xem các phần sau đây.
Ghi tệp báo lỗi
Để ghi tệp báo lỗi, bạn có thể sử dụng Cầu gỡ lỗi Android (adb) hoặc Trình phân tích bộ nhớ trong Android Studio.
Sử dụng adb để ghi tệp báo lỗi
Để ghi tệp báo lỗi bằng adb, hãy làm theo các bước sau:
- Kết nối thiết bị Android với máy tính.
- Mở lời nhắc lệnh và chuyển đến thư mục chứa các công cụ adb.
Để ghi tệp báo lỗi, hãy chạy lệnh sau :
adb shell am dumpheap my.app.name $PHONE_FILE_OUT
Để truy xuất tệp báo lỗi, hãy chạy lệnh sau:
adb pull $PHONE_FILE_OUT $LOCAL_FILE.
Sử dụng Android Studio để ghi tệp báo lỗi
Để ghi tệp báo lỗi bằng Trình phân tích bộ nhớ trong Android Studio, hãy làm theo các bước sau bước trong Android Ghi lại một tệp báo lỗi .
Phân tích tệp báo lỗi để tìm lỗi rò rỉ bộ nhớ
Sau khi ghi tệp báo lỗi, bạn có thể dùng Bộ nhớ của Android Studio Trình phân tích tài nguyên để phân tích dữ liệu đó. Để thực hiện việc này, hãy làm theo các bước sau:
Mở dự án Android trong Android Studio.
Chọn Run (Chạy), sau đó chọn cấu hình Debug (Gỡ lỗi).
Mở thẻ Android Profiler (Trình phân tích tài nguyên Android).
Chọn Bộ nhớ.
Chọn Open heap dump (Mở tệp báo lỗi) rồi chọn tệp báo lỗi mà bạn đã tạo. Trình phân tích bộ nhớ cho thấy biểu đồ về mức sử dụng bộ nhớ của ứng dụng.
Sử dụng biểu đồ để phân tích tệp báo lỗi:
Xác định các vật thể không còn được sử dụng nữa.
Xác định các đối tượng sử dụng nhiều bộ nhớ.
Xem dung lượng bộ nhớ mà mỗi đối tượng đang sử dụng.
Sử dụng thông tin này để thu hẹp hoặc tìm nguyên nhân gây rò rỉ bộ nhớ và khắc phục vấn đề đó.
Bước 5: Khắc phục lỗi rò rỉ bộ nhớ
Sau khi xác định được nguồn gốc của sự cố rò rỉ bộ nhớ, bạn có thể khắc phục. Việc khắc phục tình trạng rò rỉ bộ nhớ trong ứng dụng Android giúp cải thiện hiệu suất và độ ổn định của ứng dụng. Tuỳ thuộc vào tình huống, thông tin chi tiết sẽ khác nhau. Tuy nhiên, các đề xuất sau có thể giúp ích cho bạn:
Đảm bảo ứng dụng của bạn phân bổ và phân bổ bộ nhớ theo đề xuất của chủ đề Android Quản lý bộ nhớ của ứng dụng.
Xoá mã hoặc tài nguyên không dùng đến khỏi ứng dụng. Để biết thông tin chi tiết về các ứng dụng Android, xem Các phương pháp hay nhất dành cho ứng dụng Android.
Các công cụ gỡ lỗi khác
Sau khi các bước này hoàn tất, nếu bạn vẫn không tìm thấy và khắc phục được rò rỉ bộ nhớ, hãy thử các công cụ sau:
Gỡ lỗi bộ nhớ trong mã gốc bằng tính năng theo dõi phân bổ
Ngay cả khi bạn không trực tiếp sử dụng mã gốc, một số thư viện Android phổ biến làm, bao gồm cả các SDK của Google. Nếu bạn cho rằng sự cố rò rỉ bộ nhớ xảy ra trong mã gốc, thì sẽ có một số công cụ mà bạn có thể dùng để gỡ lỗi. Theo dõi phân bổ bằng Android Studio hoặc heapprofd (cũng tương thích với Perfetto) là một cách hiệu quả để xác định các nguyên nhân tiềm ẩn gây ra sự cố rò rỉ bộ nhớ và thường là cách nhanh nhất để gỡ lỗi.
Theo dõi phân bổ cũng có một lợi thế khác biệt là cho phép bạn chia sẻ mà không bao gồm thông tin nhạy cảm có thể được tìm thấy trong vùng nhớ khối xếp.
Xác định rò rỉ bằng LeakCanary
LeakCanary là một công cụ mạnh mẽ giúp xác định tình trạng rò rỉ bộ nhớ trong các ứng dụng Android. Để tìm hiểu thêm về cách sử dụng LeakCanary trong ứng dụng của bạn, hãy truy cập vào LeakCanary.
Cách báo cáo sự cố liên quan đến Google SDK
Nếu bạn đã thử các phương thức trong tài liệu này và nghi ngờ có sự cố rò rỉ bộ nhớ trong SDK của chúng tôi, hãy liên hệ với bộ phận hỗ trợ khách hàng kèm theo nhiều thông tin sau nhất có thể:
Các bước để tạo lại sự cố rò rỉ bộ nhớ. Nếu các bước này đòi hỏi việc lập trình phức tạp, thì việc sao chép đoạn mã tạo lại vấn đề vào ứng dụng mẫu của chúng ta có thể sẽ giúp ích và cung cấp các bước bổ sung cần thực hiện trong giao diện người dùng để kích hoạt rò rỉ.
Tệp báo lỗi được thu thập từ ứng dụng của bạn có vấn đề được tạo lại. Ghi vùng nhớ khối xếp tệp kết xuất tại hai thời điểm khác nhau cho thấy mức sử dụng bộ nhớ đã tăng lên đáng kể.
Nếu dự kiến sẽ có sự cố rò rỉ bộ nhớ gốc, hãy chia sẻ thông tin phân bổ theo dõi đầu ra từ heapprofd.
Báo cáo lỗi được nhận sau khi bạn tái tạo tình trạng rò rỉ.
Dấu vết ngăn xếp của mọi sự cố liên quan đến bộ nhớ.
Lưu ý quan trọng: Dấu vết ngăn xếp thường không đủ để gỡ lỗi sự cố bộ nhớ, do đó, hãy đảm bảo bạn cũng cung cấp một trong số các biểu mẫu khác thông tin.