Heap_Size_Overflow_Android內(nèi)存機(jī)制及溢出_第1頁(yè)
Heap_Size_Overflow_Android內(nèi)存機(jī)制及溢出_第2頁(yè)
Heap_Size_Overflow_Android內(nèi)存機(jī)制及溢出_第3頁(yè)
全文預(yù)覽已結(jié)束

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

1、Android 的內(nèi)存機(jī)制和溢出說(shuō)明An droid的虛擬機(jī)是基于寄存器的Dalvik,它的最大堆大小一般是16M。但是An droid采用的是 Java 語(yǔ)言編寫,所在很大程度上, Android 的內(nèi)存機(jī)制等同于 Java 的內(nèi)存機(jī)制 (Java 內(nèi)存機(jī)制在網(wǎng)上帖子很多,大家有興趣了解的可以去谷歌或者百度查找一些資料)。 因此在一些程序員開(kāi)發(fā)的時(shí)候,內(nèi)存的限制問(wèn)題給很多初學(xué)開(kāi)發(fā)者帶來(lái)內(nèi)存溢出等嚴(yán)重問(wèn) 題。在我們不使用一些內(nèi)存的時(shí)候, 我們要盡量在 Android 或者其他平臺(tái)上避免在運(yùn)行其他 程序時(shí), 保存必要的狀態(tài), 使得一些死進(jìn)程所帶來(lái)的內(nèi)存問(wèn)題, 應(yīng)該盡量在關(guān)閉程序或者保 存狀態(tài)的時(shí)

2、候釋放掉。這樣能提高系統(tǒng)在運(yùn)行方面的流暢性。Android 的內(nèi)存主要表現(xiàn)在:1. 在 Android 平臺(tái)上,長(zhǎng)期保持一些資源的引用,造成一些內(nèi)存不能釋放,帶來(lái)的內(nèi)存泄露問(wèn)題很多。 比如: Context (下文中提到的 Activity 都是 Context ),在一些 你需要保持你的首個(gè)類對(duì)象狀態(tài),并且把狀態(tài)傳入其他類對(duì)象中時(shí),這樣消除掉首 個(gè)類對(duì)象之前,你必須先把接收類對(duì)象釋放掉。需要注意一點(diǎn)的是:因?yàn)樵贘ava 或者 Android 內(nèi)存機(jī)制中,頂點(diǎn)的結(jié)點(diǎn)釋放前必須保證其他對(duì)象沒(méi)有調(diào)用才能被系統(tǒng)GC回收釋放。我們看一段代碼:Overrideprotected void onCreat

3、e(Bundle state) super.onCreate(state);TextView label = new TextView(this); label.setText("Leaks are bad"); setContentView(label); 這個(gè)代碼的意思就是我們把一個(gè) TextView 的實(shí)例加載到了我們正在運(yùn)行的Activity( Con text )當(dāng)中,因此,通過(guò) GC回收機(jī)制,我們知道,要釋放Co ntext,就必須先釋放掉引用他的一些對(duì)象。如果沒(méi)有,那在要釋放Context 的時(shí)候,你會(huì)發(fā)現(xiàn)會(huì)有大量的內(nèi)存溢出。所以在你不小心的情況下內(nèi)存溢出是一

4、件非常容易的事 情。2. 保存一些對(duì)象時(shí),同時(shí)也會(huì)造成內(nèi)存泄露 。最簡(jiǎn)單的比如說(shuō)位圖( Bitmap ),比如 說(shuō):在屏幕旋轉(zhuǎn)時(shí),會(huì)破壞當(dāng)前保持的一個(gè) Activity 狀態(tài),并且重新申請(qǐng)生成新的 Activity ,直到新的 Activity 狀態(tài)被保存。我們?cè)倏匆欢未a:private static Drawable sBackground;Overrideprotected void onCreate(Bundle state) super.onCreate(state);TextView label = new TextView(this); label.setText("L

5、eaks are bad");if (sBackground = null) sBackground = getDrawable(R.drawable.large_bitmap); label.setBackgroundDrawable(sBackground); setContentView(label); 這個(gè)代碼是非??斓耐瑫r(shí)也是錯(cuò)誤的。它的內(nèi)存泄露很容易出在屏幕轉(zhuǎn)移的方 向上。 雖然我們會(huì)發(fā)現(xiàn)沒(méi)有顯示的保存 Context 這個(gè)實(shí)例, 但是當(dāng)我們把繪制的圖 連接到一個(gè)視圖的時(shí)候, Drawable 就會(huì)將被 View 設(shè)置為回調(diào),這就說(shuō)明,在上述 的代碼中,其實(shí)在繪制 Tex

6、tView 到活動(dòng)中的時(shí)候,我們已經(jīng)引用到了這個(gè) Activity 。鏈接情況可以表現(xiàn)為: Drawable->TextView->Context 。所以在想要釋放 Context 的時(shí)候,其實(shí)還是保存在內(nèi)存中,并沒(méi)有得到釋放。 如何避免這種情況:主要在于。線程最容易出錯(cuò)。大家不要小看線程,在 Android 里面線程最容易造成內(nèi)存泄露。線程產(chǎn)生內(nèi)存泄露的主要原因在于線程生命周期的 不可控。下面有一段代碼: public class MyTest extends Activity Overridepublic void onCreate(Bundle savedInstanceSt

7、ate) super.onCreate(savedInstanceState); setContentView(R.layout.main);new MyThread().start();private class MyThread extends ThreadOverridepublic void run() super.run();/do somthing 代碼很簡(jiǎn)單, 但是在 Android 上又來(lái)新問(wèn)題了, 當(dāng)我們?cè)谇袚Q視圖屏幕的時(shí)候 (橫豎屏),就會(huì)重新建立橫屏或者豎屏的 Activity 。我們形象的認(rèn)為之前建立 的 Activity 會(huì)被回收,但是事實(shí)如何呢? Java 機(jī)制不會(huì)

8、給你同樣的感受,在我們 釋放 Activity 之前, 因?yàn)?run 函數(shù)沒(méi)有結(jié)束, 這樣 MyThread 并沒(méi)有銷毀, 因此引 用它的 Activity ( Mytest )也有沒(méi)有被銷毀,因此也帶來(lái)的內(nèi)存泄露問(wèn)題。有些人喜歡用 Android 提供的 AsyncTask ,但事實(shí)上 AsyncTask 的問(wèn)題更加嚴(yán) 重, Thread 只有在 run 函數(shù)不結(jié)束時(shí)才出現(xiàn)這種內(nèi)存泄露問(wèn)題,然而 AsyncTask 內(nèi)部的實(shí)現(xiàn)機(jī)制是運(yùn)用了 ThreadPoolExcutor, 該類產(chǎn)生的 Thread 對(duì)象的生命周期 是不確定的,是應(yīng)用程序無(wú)法控制的,因此如果 AsyncTask 作為 Ac

9、tivity 的內(nèi)部 類,就更容易出現(xiàn)內(nèi)存泄露的問(wèn)題。線程問(wèn)題的改進(jìn)方式主要有: 將線程的內(nèi)部類,改為靜態(tài)內(nèi)部類。在程序中盡量采用弱引用保存 Context 。3. 萬(wàn)惡的 bitmap 。Bitmap 是一個(gè)很萬(wàn)惡的對(duì)象,對(duì)于一個(gè)內(nèi)存對(duì)象,如果該對(duì)象所占內(nèi)存過(guò)大,在超 出了系統(tǒng)的內(nèi)存限制時(shí)候,內(nèi)存泄露問(wèn)題就很明顯了。解決 bitmap 主要是要解決在內(nèi)存盡量不保存它或者使得采樣率變小。在很多場(chǎng)合 下,因?yàn)槲覀兊膱D片像素很高,而對(duì)于手機(jī)屏幕尺寸來(lái)說(shuō)我們并不用那么高像素比 例的圖片來(lái)加載時(shí),我們就可以先把圖片的采樣率降低在做原來(lái)的 UI 操作。 如果在我們不需要保存 bitmap 對(duì)象的引用時(shí)候

10、, 我們還可以用軟引用來(lái)做替換。 具 體的實(shí)例代碼 google 上面也有很多。綜上所述,要避免內(nèi)存泄露,主要要遵循以下幾點(diǎn):第一: 不要為 Context 長(zhǎng)期保存引用 (要引用 Context 就要使得引用對(duì)象和它本身的生 命周期保持一致)。第二:如果要使用到 Context ,盡量使用 Application Context 去代替 Context ,因?yàn)?Application Context的生命周期較長(zhǎng),引用情況下不會(huì)造成內(nèi)存泄露問(wèn)題第三:在你不控制對(duì)象的生命周期的情況下避免在你的 Activity 中使用 static 變量。 盡量使用 WeakReference 去代替一個(gè) static 。第四: 垃圾回收器并不保證能準(zhǔn)確回收內(nèi)存,這樣在使用自己需要的內(nèi)容時(shí), 主要生命周期和及時(shí)釋放掉不需要的對(duì)象。盡量在 Activity 的生命周期結(jié)束時(shí),在 onDestroy 中把 我們做引用的其他對(duì)象做釋放,比如: cursor.close() 。其實(shí)我們可以在很多

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論