Android 内存泄露与解决方案

内存泄露

Java内存泄漏指的是进程中某些对象(垃圾对象)已经没有使用价值了,但是它们却可以直接或间接地引用到gc
roots导致无法被GC回收。无用的对象占据着内存空间,使得实际可使用内存变小,形象地说法就是内存泄漏了。下面分析一些可能导致内存泄漏的情景。

  • 非静态内部类的静态实例容易造成内存泄漏
  • activity使用静态成员
  • handler
    非静态
  • 注册某个对象后未反注册
  • 资源对象没关闭造成的内存泄露
  • 构造Adapter时,没有使用缓存的 convertView

以上分析只是常见的问题,本质上是 
*
全局进程(process-global)的static变量。这个无视应用的状态,持有Activity的强引用的怪物 
* 活在Activity生命周期之外的线程。没有清空对Activity的强引用 
可以参考下面文章的讲解及解决方式。本文重点是关注handler这类非静态引起及使用
WeakReference, SoftReference来处理。

[译]Android内存泄漏的八种可能(上)

[译]Android防止内存泄漏的八种方法(下)

引例

先看 下面代码

public class SampleActivity extends Activity {

  private final Handler mLeakyHandler = new Handler() {
    @Override
    public void handleMessage(Message msg) {
      // ...
    }
  };

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    // Post a message and delay its execution for 10 minutes.
    mLeakyHandler.postDelayed(new Runnable() {
      @Override
      public void run() { /* ... */ }
    }, 1000 * 60 * 10);

    // Go back to the previous Activity.
    finish();
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

Activity的销毁会到10分钟后的handler执行完毕。解决办法其实有比较多的方案,这里使用WeakReference

解决方案

public class SampleActivity extends Activity {

  /**
   * Instances of static inner classes do not hold an implicit
   * reference to their outer class.
   */
  private static class MyHandler extends Handler {
    private final WeakReference<SampleActivity> mActivity;

    public MyHandler(SampleActivity activity) {
      mActivity = new WeakReference<SampleActivity>(activity);
    }

    @Override
    public void handleMessage(Message msg) {
      SampleActivity activity = mActivity.get();
      if (activity != null) {
        // ...
      }
    }
  }

  private final MyHandler mHandler = new MyHandler(this);

  /**
   * Instances of anonymous classes do not hold an implicit
   * reference to their outer class when they are "static".
   */
  private static final Runnable sRunnable = new Runnable() {
      @Override
      public void run() { /* ... */ }
  };

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    // Post a message and delay its execution for 10 minutes.
    mHandler.postDelayed(sRunnable, 1000 * 60 * 10);

    // Go back to the previous Activity.
    finish();
  }
}


  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46

这样一来Activity不再是handler的强引用了,对于重度Activity类如此来解决还是比较好的。 
Finally understanding how references work in Android and
Java
讲到了
WeakReference,SoftReference,PhantomReference,Strong reference.一般SoftReference更适合做Cache,在系统内存不足时才会清理。

Strong
reference
: strong references are
the ordinary references in Java. Anytime we create a new object, a strong
reference is by default created.

WeakReference:
a weak reference is a reference not strong enough to keep the object in memory.
If we try to determine if the object is strongly referenced and it happened to
be through WeakReferences, the object will be garbage-collected.

SoftReference:
think of a SoftReference as a stronger WeakReference. Whereas a WeakReference
will be collected immediately, a SoftReference will beg to the GC to stay in
memory unless there is no other option. The Garbage Collector algorithms are
really thrilling and something you can dive in for hours and hours without
getting tired. But basically, they say “I will always reclaim the WeakReference.
If the object is a SoftReference, I will decide what to do based on the
ecosystem conditions”. This makes a SoftReference very useful for the
implementation of a cache: as long as the memory is plenty, we do not have to
worry of manually removing objects.

PhantomReference:
Ah, PhantomReferences! I think I can count on the fingers of one hand how often
I saw them used in a production environment. An Object that has only being
referenced through a PhantomReference them can be collected whenever the Garbage
Collector wants. No further explanations, no “call me back”. This makes it hard
to characterise. Why would we like to use such a thing? Are the other ones not
problematic enough? Why did I choose to be a programmer? PhantomReference can be
used exactly to detect when an object has been removed from memory. Being fully
transparent, I recall two occasions when I had to use a PhantomReference in my
entire professional career. So do not get stressed if they are hard to
understand now.

参考链接

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇