生活随笔
收集整理的這篇文章主要介紹了
Android之内存泄露、内存溢出、内存抖动分析
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
? 內(nèi)存
JAVA是在JVM所虛擬出的內(nèi)存環(huán)境中運(yùn)行的,內(nèi)存分為三個(gè)區(qū):堆、棧和方法區(qū)。
棧(stack):是簡(jiǎn)單的數(shù)據(jù)結(jié)構(gòu),程序運(yùn)行時(shí)系統(tǒng)自動(dòng)分配,使用完畢后自動(dòng)釋放。優(yōu)點(diǎn):速度快。
堆(heap):用于存放由new創(chuàng)建的對(duì)象和數(shù)組。在堆中分配的內(nèi)存,一方面由java虛擬機(jī)自動(dòng)垃圾回收器來(lái)管理,另一方面還需要程序員提供修養(yǎng),防止內(nèi)存泄露問(wèn)題。
方法區(qū)(method):又叫靜態(tài)區(qū),跟堆一樣,被所有的線程共享。方法區(qū)包含所有的class和static變量。
Java GC
GC可以自動(dòng)清理堆中不在使用(不在有對(duì)象持有該對(duì)象的引用)的對(duì)象。
在JAVA中對(duì)象如果再?zèng)]有引用指向該對(duì)象,那么該對(duì)象就無(wú)從處理或調(diào)用該對(duì)象,這樣的對(duì)象稱為不可到達(dá)(unreachable)。垃圾回收用于釋放不可到達(dá)的對(duì)象所占據(jù)的內(nèi)存。
對(duì)android來(lái)說(shuō),內(nèi)存使用尤為吃緊,最開(kāi)始的app進(jìn)程最大分配才8M的內(nèi)存,漸漸增加到16M、32M、64M,但是和服務(wù)端相比還是很渺小的。如果對(duì)象回收不及時(shí),很容易出現(xiàn)OOM錯(cuò)誤。
?
內(nèi)存泄露
什么是內(nèi)存泄露?程序通過(guò)new分配內(nèi)存,在使用完畢后沒(méi)有釋放,造成內(nèi)存占用。這塊內(nèi)存不受GC控制,無(wú)法通過(guò)GC回收。 主要表現(xiàn)在:當(dāng)一個(gè)對(duì)象已經(jīng)不再使用,本該被回收的,但是另外一個(gè)正在使用的對(duì)象持有它的引用從而就導(dǎo)致對(duì)象不能被回收。這種對(duì)象存在堆內(nèi)存中,就產(chǎn)生了內(nèi)存泄漏。
危害?內(nèi)存泄漏對(duì)于app沒(méi)有直接的危害,即使app有發(fā)生內(nèi)存泄漏的情況,也不一定會(huì)引起app崩潰,但是會(huì)增加app內(nèi)存的占用。內(nèi)存得不到釋放,慢慢的會(huì)造成app內(nèi)存溢出。解決內(nèi)存泄漏目的就是防止app發(fā)生內(nèi)存溢出。
內(nèi)存泄露主要表現(xiàn)的當(dāng)Activity在finish的時(shí)候,由于對(duì)象持有對(duì)Activity的引用,造成Activity沒(méi)有被及時(shí)回收。總結(jié)了下大致有5種情況造成內(nèi)存泄露,(1)static變量、匿名類的使用 (2)線程執(zhí)行處理(3)各種監(jiān)聽(tīng)回調(diào)處置(4)Bitmap等回收處置(5)集合類只有增操作卻沒(méi)有減操作。 常見(jiàn)情況 1)外部類持有Activity的靜態(tài)引用
[java]?view plaincopy
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)異步執(zhí)行耗時(shí)任務(wù)期間時(shí),Thread、AsyncTask、TimeTask持有的Activty進(jìn)行finish時(shí),Activity實(shí)例不會(huì)被回收。
[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內(nèi)部類造成內(nèi)存泄露。 Handler為非靜態(tài)內(nèi)部類時(shí)會(huì)隱式持有當(dāng)前activity引用。當(dāng)Activity被 finish()時(shí),若Handler有未處理完或延遲的消息(主要是Handler牽扯到線程問(wèn)題),會(huì)造成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生命周期結(jié)束前,確保Handler移除消息(mMyHanlder.removeCallbacksAndMessages(null);)或者使用靜態(tài)Handler內(nèi)部類。 如:使用了弱引用替代強(qiáng)引用.
[java]?view plaincopy
static?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)?{??????????????????????????????}??????????}??????}?? 建議熟悉下:強(qiáng)引用(StrongReference)、軟引用(SoftReference)、弱引用(WeakReference)、虛引用(PhantomReference) 4)匿名內(nèi)部類的使用。
[java]?view plaincopy
public?class?DemoActivity?extends?AppCompatActivity?{????????????Runnable?runnable?=?new?Runnable()?{??????????@Override??????????public?void?run()?{????????????}??????};?? runnable默認(rèn)會(huì)持有DemoActivity的引用。若Activity被finish的時(shí)候,如線程在使用runnable,則會(huì)造成內(nèi)存泄露。 5)構(gòu)造Adapter時(shí)沒(méi)有使用緩存的 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)?當(dāng)使用了BraodcastReceiver、Cursor、Bitmap等資源時(shí),若沒(méi)有及時(shí)釋放,則會(huì)引起內(nèi)存泄漏。 7)集合類的不當(dāng)使用。
更多內(nèi)存泄露可以通過(guò)檢測(cè)工具發(fā)現(xiàn)。檢測(cè)工具主要有MAT、Memory Monitor 、Allocation Tracker 、Heap Viewer、LeakCanary
?
內(nèi)存溢出
什么是內(nèi)存溢出?out of memory。?程序向系統(tǒng)申請(qǐng)的內(nèi)存空間超出了系統(tǒng)能給的。內(nèi)存泄露很容易引起OOM。
內(nèi)存抖動(dòng)
內(nèi)存抖動(dòng)是指在短時(shí)間內(nèi)有大量的對(duì)象被創(chuàng)建或者被回收的現(xiàn)象,主要是循環(huán)中大量創(chuàng)建、回收對(duì)象。這種情況應(yīng)當(dāng)盡量避免。
總結(jié)
以上是生活随笔為你收集整理的Android之内存泄露、内存溢出、内存抖动分析的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。