国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Android - android內存及內存溢出分析詳解

android內存及內存溢出分析詳解

2021-02-05 14:53Android開發網 Android

這篇文章詳細介紹了android內存及內存溢出的問題,有需要的朋友可以參考一下

一、Android的內存機制
    Android的程序由Java語言編寫,所以Android的內存管理與Java的內存管理相似。程序員通過new為對象分配內存,所有對象在java堆內分配空間;然而對象的釋放是由垃圾回收器來完成的。C/C++中的內存機制是“誰污染,誰治理”,java的就比較人性化了,給我們請了一個專門的清潔工(GC)。
    那么GC怎么能夠確認某一個對象是不是已經被廢棄了呢?Java采用了有向圖的原理。Java將引用關系考慮為圖的有向邊,有向邊從引用者指向引用對象。線程對象可以作為有向圖的起始頂點,該圖就是從起始頂點開始的一棵樹,根頂點可以到達的對象都是有效對象,GC不會回收這些對象。如果某個對象 (連通子圖)與這個根頂點不可達(注意,該圖為有向圖),那么我們認為這個(這些)對象不再被引用,可以被GC回收。
二、Android的內存溢出
    Android的內存溢出是如何發生的?
    Android的虛擬機是基于寄存器的Dalvik,它的最大堆大小一般是16M,有的機器為24M。因此我們所能利用的內存空間是有限的。如果我們的內存占用超過了一定的水平就會出現OutOfMemory的錯誤。
為什么會出現內存不夠用的情況呢?我想原因主要有兩個:
•由于我們程序的失誤,長期保持某些資源(如Context)的引用,造成內存泄露,資源造成得不到釋放。
•保存了多個耗用內存過大的對象(如Bitmap),造成內存超出限制。
三、萬惡的static
    static是Java中的一個關鍵字,當用它來修飾成員變量時,那么該變量就屬于該類,而不是該類的實例。所以用static修飾的變量,它的生命周期是很長的,如果用它來引用一些資源耗費過多的實例(Context的情況最多),這時就要謹慎對待了。

復制代碼 代碼如下:


public class ClassName { 
     private static Context mContext; 
     //省略 


以上的代碼是很危險的,如果將Activity賦值到么mContext的話。那么即使該Activity已經onDestroy,但是由于仍有對象保存它的引用,因此該Activity依然不會被釋放。
    我們舉Android文檔中的一個例子。

復制代碼 代碼如下:


private static Drawable sBackground; 
 @Override 
 protected void onCreate(Bundle state) { 
   super.onCreate(state); 
   TextView label = new TextView(this); 
   label.setText("Leaks are bad"); 
   if (sBackground == null) { 
     sBackground = getDrawable(R.drawable.large_bitmap); 
   } 
   label.setBackgroundDrawable(sBackground); 
   setContentView(label); 
 } 


    sBackground, 是一個靜態的變量,但是我們發現,我們并沒有顯式的保存Contex的引用,但是,當Drawable與View連接之后,Drawable就將View設置為一個回調,由于View中是包含Context的引用的,所以,實際上我們依然保存了Context的引用。這個引用鏈如下:
    Drawable->TextView->Context
    所以,最終該Context也沒有得到釋放,發生了內存泄露。
    如何才能有效的避免這種引用的發生呢?
    第一,應該盡量避免static成員變量引用資源耗費過多的實例,比如Context。
    第二、Context盡量使用Application Context,因為Application的Context的生命周期比較長,引用它不會出現內存泄露的問題。
    第三、使用WeakReference代替強引用。比如可以使用WeakReference<Context> mContextRef;
    該部分的詳細內容也可以參考Android文檔中Article部分。
四、都是線程惹的禍
    線程也是造成內存泄露的一個重要的源頭。線程產生內存泄露的主要原因在于線程生命周期的不可控。我們來考慮下面一段代碼。

復制代碼 代碼如下:


public class MyActivity extends Activity { 
    @Override 
    public void onCreate(Bundle savedInstanceState) { 
        super.onCreate(savedInstanceState); 
        setContentView(R.layout.main); 
        new MyThread().start(); 
    } 
    private class MyThread extends Thread{ 
        @Override 
        public void run() { 
            super.run(); 
            //do somthing 
        } 
    } 


    這段代碼很平常也很簡單,是我們經常使用的形式。我們思考一個問題:假設MyThread的run函數是一個很費時的操作,當我們開啟該線程后,將設備的橫屏變為了豎屏,一般情況下當屏幕轉換時會重新創建Activity,按照我們的想法,老的Activity應該會被銷毀才對,然而事實上并非如此。
    由于我們的線程是Activity的內部類,所以MyThread中保存了Activity的一個引用,當MyThread的run函數沒有結束時,MyThread是不會被銷毀的,因此它所引用的老的Activity也不會被銷毀,因此就出現了內存泄露的問題。
    有些人喜歡用Android提供的AsyncTask,但事實上AsyncTask的問題更加嚴重,Thread只有在run函數不結束時才出現這種內存泄露問題,然而AsyncTask內部的實現機制是運用了ThreadPoolExcutor,該類產生的Thread對象的生命周期是不確定的,是應用程序無法控制的,因此如果AsyncTask作為Activity的內部類,就更容易出現內存泄露的問題。
    這種線程導致的內存泄露問題應該如何解決呢?
    第一、將線程的內部類,改為靜態內部類。
    第二、在線程內部采用弱引用保存Context引用。
    解決的模型如下:

復制代碼 代碼如下:


public abstract class WeakAsyncTask<Params, Progress, Result, WeakTarget> extends 
        AsyncTask<Params, Progress, Result> { 
    protected WeakReference<WeakTarget> mTarget; 
    public WeakAsyncTask(WeakTarget target) { 
        mTarget = new WeakReference<WeakTarget>(target); 
    } 
    @Override 
    protected final void onPreExecute() { 
        final WeakTarget target = mTarget.get(); 
        if (target != null) { 
            this.onPreExecute(target); 
        } 
    } 
    @Override 
    protected final Result doInBackground(Params... params) { 
        final WeakTarget target = mTarget.get(); 
        if (target != null) { 
            return this.doInBackground(target, params); 
        } else { 
            return null; 
        } 
    } 
    @Override 
    protected final void onPostExecute(Result result) { 
        final WeakTarget target = mTarget.get(); 
        if (target != null) { 
            this.onPostExecute(target, result); 
        } 
    } 
    protected void onPreExecute(WeakTarget target) { 
        // No default action 
    } 
    protected abstract Result doInBackground(WeakTarget target, Params... params); 
    protected void onPostExecute(WeakTarget target, Result result) { 
        // No default action 
    } 


事實上,線程的問題并不僅僅在于內存泄露,還會帶來一些災難性的問題。由于本文討論的是內存問題,所以在此不做討論。

延伸 · 閱讀

精彩推薦
Weibo Article 1 Weibo Article 2 Weibo Article 3 Weibo Article 4 Weibo Article 5 Weibo Article 6 Weibo Article 7 Weibo Article 8 Weibo Article 9 Weibo Article 10 Weibo Article 11 Weibo Article 12 Weibo Article 13 Weibo Article 14 Weibo Article 15 Weibo Article 16 Weibo Article 17 Weibo Article 18 Weibo Article 19 Weibo Article 20 Weibo Article 21 Weibo Article 22 Weibo Article 23 Weibo Article 24 Weibo Article 25 Weibo Article 26 Weibo Article 27 Weibo Article 28 Weibo Article 29 Weibo Article 30 Weibo Article 31 Weibo Article 32 Weibo Article 33 Weibo Article 34 Weibo Article 35 Weibo Article 36 Weibo Article 37 Weibo Article 38 Weibo Article 39 Weibo Article 40
主站蜘蛛池模板: 中文字幕免费观看 | 国产精品美女久久久久久久久久久 | 日本久久精品视频 | 午夜精品影院 | 久色91| 激情欧美一区二区三区 | 国产亚洲精品久久久456 | 日日干夜夜干 | 亚洲欧美日韩精品 | 久操视频免费在线观看 | 日本视频免费高清一本18 | 午夜精品久久久久久久久 | 日韩在线观看第一页 | 国产一区中文字幕 | 国产最新视频 | 波多野结衣先锋影音 | 福利一区二区 | 蜜桃精品一区二区 | 日韩欧美国产一区二区 | 91久久精品国产 | 一区视频| 91av在线电影 | 国产精品久久久久久吹潮 | 久久久女女女女999久久 | 国产中文字幕在线 | 国产精品永久久久久久久久久 | 亚洲一区二区三区久久久 | 精品少妇一区二区三区日产乱码 | 国产一区二区三区在线 | 色九九| 99精品99 | 亚洲国产精品网站 | 一区福利| 国产综合亚洲精品一区二 | 久久久精品久久久 | 99草视频| 日韩一二 | 麻豆乱码国产一区二区三区 | 精品久久精品 | 成人免费毛片高清视频 | 国内av网站 |