Memory leak trong Android, nguyên nhân và cách xử lý (phần 2)

phần 1 mình đã giới thiệu cơ bản về Memory leak (ML) và thư viện LeakCanary (LC) giúp tìm leak.
Phần này mình sẽ lượt qua những loại ML mình đã gặp và cách xử lý.

Leak do sử dụng non static inner class

Vấn đề

Trong Java, non static inner class sẽ reference đến outer class. Trong ví dụ trên, bên trong runnable bạn có thể dùng members của MainActivity, có nghĩa là runnable reference đến MainActivity. Như vậy MainActivity sẽ không bị hủy chừng nào Thread vẫn còn đang chạy.

Giải pháp

Chuyển non static inner class thành static inner class

Bây giờ StaticRunnable sẽ không reference tới MainActivity nữa -> Leak gone 🙂

Thêm tí

Do runnable không reference tới context, giờ muốn dùng ActivityContext trong runnable thì làm thế nào?

Truyền Context vào và tạo WeakReference

Tại sao phải check null trước khi sử dụng activity?
GC sẽ lấy lại vùng nhớ của activity bất cứ lúc nào do nó được đặt trong một WeakReference.

Leak do reference ActivityContext trong Singleton

Vấn đề

Bạn sẽ nói Singleton như vậy thì không có vấn đề gì?
Nếu ai đó tạo instance của Singleton này không đúng cách sẽ sinh ra leak.

Ví dụ:

Giờ thì Activity bị leak rồi nhé.

Memory leak

Giải pháp

Thường thì Singleton sẽ đi với ApplicationContext, như vậy mình chỉ cần getApplicationContext khi tạo Singleton là xong

Leak do sử dụng Broadcast không đúng cách

Vấn đề

LC sẽ báo MainActivity bị leak:
Memory leak

Giải pháp

Unregister BroadcastReceiver. Nếu bạn register trong onCreate() thì unregister trong onDestroy(), nếu register trong onResume() thì unregister trong onPause()

Kết luận

Nguồn gốc căn cơ của leak trong Android là khi có cái gì đó giữ reference tới ActivityContext của mình. Như vậy để không bị leak thì:

  1. Hạn chế truyền ActivityContext vào trong những cái không bao giờ chết (Singleton) hoặc không biết khi nào chết (Thread), nếu có truyền thì tạo WeakReference để giữ context.
  2. Phải am hiểu Activity lifecycle để gỡ bỏ reference khi Activity bị GC sờ gáy.
  3. Dùng Context đúng phạm vi của nó, mời bạn đọc bài “Dùng Context thế nào cho đúng?” tại http://blog.appconus.com/yyyy/MM/dd/dung-thread-the-nao-cho-dung

Mình sẽ liên tục cập nhật bài này khi tìm thấy leak issue khác trong quá trình làm việc. Các bạn cũng có thể chia sẽ Memory leak mà mình đã gặp trong quá trình phát triển ứng dụng tại topic này. Cảm ơn đã quan tâm.
Coding vui vẻ.

Spread the love
  • 21
  •  
  •  
  •  
  •  
    21
    Shares

Leave a Reply

15 Comments on "Memory leak trong Android, nguyên nhân và cách xử lý (phần 2)"

avatar
  Subscribe  
newest oldest most voted
Notify of
haihack
Guest

Chào bạn,

Mình không hiểu về WeakReference lắm

Activity activity = activityWeakReference.get();
if (activity != null) {
doSomething(activity);
}

1.
“Vì GC sẽ lấy lại vùng nhớ của activity bất cứ lúc nào”, bất cứ lúc nào ở đây là “hên xui”, không thể biết trước được hả bạn
2.
Nếu activity không còn được tham chiếu thì có phải là sẽ ko còn gọi hàm doSomething() không? Như vậy theo ý mình hiểu thì việc thực hiện doSomething() cũng là “hên xui”.
3. Có thể dùng StrongReference???

QuanTran
Guest
Chào bạn haihack StrongReference là kiểu reference bình thường VD: class ABC{ Activity _activity; public void setActivity(Activity activity){ _activity = activity; } } Như vậy class ABC sẽ giữ reference của activity truyền vào cho tới khi nó được hủy, khiến cho GC không dễ dọn dẹp được activity. WeakReference thì cũng tương tự, nhưng GC có thể dọn dẹp được activity truyền vào, nhưng như thế thì ta mỗi là dùng activity đó ta phải kiểm tra nó có null hay chưa (tức đã bị dọn dẹp hay chưa). Activity activity = activityWeakReference.get(); if (activity != null) { doSomething(activity);… Read more »
haihack
Guest

hi, mình vẫn có thắc mắc

if (activity != null) {
doSomething(activity);
}

vậy nhỡ activity null thì không thực hiện hàm doSomething() nữa. Giả sử như dùng Asynctask hay Thread thì có phải nó sẽ không hoàn thành nhiệm vụ của nó được không.

vuhung3990
Guest

bài viết của bạn quả thật giúp cho mình rất nhiều, cám ơn

Định
Guest

Không biết nói gì hơn ngoài “thanks” bạn.
Mình thì vừa mới tiếp cận android đây thôi, lúc đầu nghĩ chắc nó cũng đơn giản lắm bởi vì mình có nền tảng Java Web với Application rồi. Nhưng thực sự khi tìm hiểu về android mình mới biết cái mình đã học và làm được chỉ giống như cưỡi ngựa xem hoa thôi.
Đúng là không ân hận khi học android =))

haihack
Guest

Dung Thread the nao cho-dung. Bài này bị xóa rồi bạn ơi.
http://blog.appconus.com/yyyy/MM/dd/dung-thread-the-nao-cho-dung

Anonymous
Guest

Thanks, bài rất hay.