1.記憶體溢出oom
程式發生OMM并不表示RAM不足,而是因為程式申請的java heap對象超過了dalvik vm heapgrowthlimit。也就是說,在RAM充足的情況下,也可能發生OOM。
java程式發生OMM并不是表示RAM不足,如果RAM真的不足,會發生什麼呢?這時Android的memory killer會起作用,當RAM所剩不多時,memory killer會殺死一些優先級比較低的程序來釋放實體記憶體,讓高優先級程式得到更多的記憶體
這個是因為Android系統對dalvik的vm heapsize作了硬性限制,當java程序申請的java空間超過門檻值時,就會抛出OOM異常(這個門檻值可以是48M、24M、16M等,視機型而定),可以通過adb shell getprop | grep dalvik.vm.heapgrowthlimit檢視此值。
也就是說,程式發生OMM并不表示RAM不足,而是因為程式申請的java heap對象超過了dalvik vm heapgrowthlimit。也就是說,在RAM充足的情況下,也可能發生OOM.
即發生記憶體洩露,是oom的主要源頭。
2.記憶體洩露
Java記憶體洩漏指的是程序中某些對象(垃圾對象)已經沒有使用價值了,但是它們卻可以直接或間接地引用到gc roots導緻無法被GC回收。無用的對象占據着記憶體空間,使得實際可使用記憶體變小,形象地說法就是記憶體洩漏了.記憶體洩露的原因以及解決方法有:
2.1非靜态内部類的靜态執行個體容易造成記憶體洩漏
對于lauchMode不是singleInstance的Activity, 應該避免在activity裡面執行個體化其非靜态内部類的靜态執行個體。
2.2activity使用靜态成員
·不要對activity的context長期引用(一個activity的引用的生存周期應該和activity的生命周期相同)
·如果可以的話,盡量使用關于application的context來替代和activity相關的context
·如果一個acitivity的非靜态内部類的生命周期不受控制,那麼避免使用它;正确的方法是使用一個靜态的内部類,并且對它的外部類有一WeakReference,就像在ViewRootImpl中内部類W所做的那樣。
2.3使用handler時的記憶體問題
This Handler class should be static or leaks might occur (com.example.ta.HandlerActivity.1)
可以将handler變為static ,或者添加弱引用
public class SampleActivity extends Activity {
/**
* 使用靜态的内部類,不會持有目前對象的引用
*/
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);
/**
* 使用靜态的内部類,不會持有目前對象的引用
*/
private static final Runnable sRunnable = new Runnable() {
@Override
public void run() { }
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 發送一個10分鐘後執行的一個消息
mHandler.postDelayed(sRunnable, 600000);
// 結束
finish();
}
}
因為HandlerThread實作的run方法是一個無限循環,它不會自己結束,線程的生命周期超過了activity生命周期,當橫豎屏切換,HandlerThread線程的數量會随着activity重建次數的增加而增加。
應該在onDestroy時将線程停止掉:mThread.getLooper().quit();
另外,對于不是HandlerThread的線程,也應該確定activity消耗後,線程已經終止,可以這樣做:在onDestroy時調用mThread.join();
2.4注冊某個對象後未取消注冊
注冊廣播接收器、注冊觀察者等等,當它不用時,及時unregister
2.5集合中對象沒清理造成的記憶體洩露
2.6資源對象沒關閉造成的記憶體洩露
對檔案,資源進行調用,cursor等,當資源對象加載完成,應該及時colse();
參考文檔:http://blog.csdn.net/gemmem/article/details/13017999