Android之内存泄露、内存溢出、内存抖动分析
生活随笔
收集整理的這篇文章主要介紹了
Android之内存泄露、内存溢出、内存抖动分析
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
?
棧(stack):是簡單的數據結構,程序運行時系統自動分配,使用完畢后自動釋放。優點:速度快。
堆(heap):用于存放由new創建的對象和數組。在堆中分配的內存,一方面由java虛擬機自動垃圾回收器來管理,另一方面還需要程序員提供修養,防止內存泄露問題。
方法區(method):又叫靜態區,跟堆一樣,被所有的線程共享。方法區包含所有的class和static變量。public?class?MainActivity?extends?AppCompatActivity?{?? ????static?Activity?activity;?? ?? ????@Override?? ????protected?void?onCreate(Bundle?savedInstanceState)?{?? ????????super.onCreate(savedInstanceState);?? ????????setContentView(R.layout.activity_main);?? ????????CommUtil?commUtil?=?CommUtil.getInstance(this);?? ????}?? [java]?view plaincopy public?class?CommUtils?{?? ????private?static?CommUtils?instance;?? ????private?Context?context;?? ?? ????private?CommUtils(Context?context)?{?? ????????this.context?=?context;?? ????}?? ?? ????public?static?CommUtils?getInstance(Context?context)?{?? ????????if?(instance?==?null)?{?? ????????????instance?=?new?CommUtils(context);?? ????????}?? ????????return?instance;?? ????}?? }?? 2)異步執行耗時任務期間時,Thread、AsyncTask、TimeTask持有的Activty進行finish時,Activity實例不會被回收。 [java]?view plaincopy protected?void?onCreate(Bundle?savedInstanceState)?{?? ????????super.onCreate(savedInstanceState);?? ????????setContentView(R.layout.activity_main);?? ????????new?AsyncTask<String,?Void,?String>()?{?? ????????????@Override?? ????????????protected?String?doInBackground(String...?params)?{?? ????????????????for?(int?i?=?0;?i?<?15;?i++)?{?? ????????????????????try?{?? ????????????????????????Log.e("MainActivity2",?"dddd"?+?i?+?MainActivity2.this.getLocalClassName());?? ????????????????????????Thread.sleep(1000);?? ????????????????????}?catch?(InterruptedException?e)?{?? ????????????????????????e.printStackTrace();?? ????????????????????}?? ????????????????}?? ????????????????return?null;?? ????????????}?? ?? ????????????@Override?? ????????????protected?void?onPostExecute(String?s)?{?? ????????????????super.onPostExecute(s);?? ????????????}?? ????????}.execute();?? ????}?? 3)Handler內部類造成內存泄露。 Handler為非靜態內部類時會隱式持有當前activity引用。當Activity被 finish()時,若Handler有未處理完或延遲的消息(主要是Handler牽扯到線程問題),會造成activity不能被回收。 [java]?view plaincopy MyHandler?myHandler?=?new?MyHandler();?? ?? ???@Override?? ???protected?void?onCreate(@Nullable?Bundle?savedInstanceState)?{?? ???????super.onCreate(savedInstanceState);?? ???????myHandler.postDelayed(new?Runnable()?{?? ???????????@Override?? ???????????public?void?run()?{?? ?? ???????????}?? ???????},?50?*?1000);?? ???}?? ?? ???class?MyHandler?extends?Handler?{?? ?? ???????@Override?? ???????public?void?handleMessage(Message?msg)?{?? ???????????super.handleMessage(msg);?? ???????}?? ???}??
解決辦法:在Activity生命周期結束前,確保Handler移除消息(mMyHanlder.removeCallbacksAndMessages(null);)或者使用靜態Handler內部類。 如:使用了弱引用替代強引用. [java]?view plaincopystatic?MyHandler?myHandler;?? ????@Override?? ????protected?void?onCreate(@Nullable?Bundle?savedInstanceState)?{?? ????????super.onCreate(savedInstanceState);?? ????????myHandler?=?new?MyHandler(this);?? ????}?? ????static?class?MyHandler?extends?Handler?{?? ????????WeakReference<Activity>?mActivityReference;?? ?? ????????MyHandler(Activity?activity)?{?? ????????????mActivityReference?=?new?WeakReference<Activity>(activity);?? ????????}?? ?? ????????@Override?? ????????public?void?handleMessage(Message?msg)?{?? ????????????final?Activity?activity?=?mActivityReference.get();?? ????????????if?(activity?!=?null)?{?? ????????????????//....?? ????????????}?? ????????}?? ????}?? 建議熟悉下:強引用(StrongReference)、軟引用(SoftReference)、弱引用(WeakReference)、虛引用(PhantomReference) 4)匿名內部類的使用。 [java]?view plaincopy public?class?DemoActivity?extends?AppCompatActivity?{?? ?????? ????Runnable?runnable?=?new?Runnable()?{?? ????????@Override?? ????????public?void?run()?{?? ?? ????????}?? ????};?? runnable默認會持有DemoActivity的引用。若Activity被finish的時候,如線程在使用runnable,則會造成內存泄露。 5)構造Adapter時沒有使用緩存的 convertView [java]?view plaincopy public?View?getView(int?position,?View?convertView,?ViewGroup?parent)?{?? ????????View?view?=?null;?? ????????if?(convertView?==?null)?? ????????????convertView?=?View.inflate(this,?R.layout.item_layout,?false);?? ????????view?=?convertView;?? ????????return?view;?? ????}?? 6)?當使用了BraodcastReceiver、Cursor、Bitmap等資源時,若沒有及時釋放,則會引起內存泄漏。 7)集合類的不當使用。
內存
JAVA是在JVM所虛擬出的內存環境中運行的,內存分為三個區:堆、棧和方法區。棧(stack):是簡單的數據結構,程序運行時系統自動分配,使用完畢后自動釋放。優點:速度快。
堆(heap):用于存放由new創建的對象和數組。在堆中分配的內存,一方面由java虛擬機自動垃圾回收器來管理,另一方面還需要程序員提供修養,防止內存泄露問題。
方法區(method):又叫靜態區,跟堆一樣,被所有的線程共享。方法區包含所有的class和static變量。
Java GC
GC可以自動清理堆中不在使用(不在有對象持有該對象的引用)的對象。
在JAVA中對象如果再沒有引用指向該對象,那么該對象就無從處理或調用該對象,這樣的對象稱為不可到達(unreachable)。垃圾回收用于釋放不可到達的對象所占據的內存。
對android來說,內存使用尤為吃緊,最開始的app進程最大分配才8M的內存,漸漸增加到16M、32M、64M,但是和服務端相比還是很渺小的。如果對象回收不及時,很容易出現OOM錯誤。
?
內存泄露
什么是內存泄露?程序通過new分配內存,在使用完畢后沒有釋放,造成內存占用。這塊內存不受GC控制,無法通過GC回收。 主要表現在:當一個對象已經不再使用,本該被回收的,但是另外一個正在使用的對象持有它的引用從而就導致對象不能被回收。這種對象存在堆內存中,就產生了內存泄漏。危害?內存泄漏對于app沒有直接的危害,即使app有發生內存泄漏的情況,也不一定會引起app崩潰,但是會增加app內存的占用。內存得不到釋放,慢慢的會造成app內存溢出。解決內存泄漏目的就是防止app發生內存溢出。
內存泄露主要表現的當Activity在finish的時候,由于對象持有對Activity的引用,造成Activity沒有被及時回收。總結了下大致有5種情況造成內存泄露,(1)static變量、匿名類的使用 (2)線程執行處理(3)各種監聽回調處置(4)Bitmap等回收處置(5)集合類只有增操作卻沒有減操作。 常見情況 1)外部類持有Activity的靜態引用 [java]?view plaincopy解決辦法:在Activity生命周期結束前,確保Handler移除消息(mMyHanlder.removeCallbacksAndMessages(null);)或者使用靜態Handler內部類。 如:使用了弱引用替代強引用. [java]?view plaincopy
更多內存泄露可以通過檢測工具發現。檢測工具主要有MAT、Memory Monitor 、Allocation Tracker 、Heap Viewer、LeakCanary
?
內存溢出
什么是內存溢出?out of memory。?程序向系統申請的內存空間超出了系統能給的。內存泄露很容易引起OOM。內存抖動
內存抖動是指在短時間內有大量的對象被創建或者被回收的現象,主要是循環中大量創建、回收對象。這種情況應當盡量避免。總結
以上是生活随笔為你收集整理的Android之内存泄露、内存溢出、内存抖动分析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: flex和box、flexbox高度自适
- 下一篇: 类的继承定义一个computer类在此基