王剛メモリ最適化パフォーマンスの最適化----(a)の(ランタイムガベージコレクション機構のデータ領域でのJava仮想マシンがメモリの回復を決定する方法で、Javaの4つの参照、メモリリーク)

まず:メモリ最適化ツール
メモリ最適化ツール:DDMS MATファインダー-活動、LeakCanary 、LeakInspector など。
第二:実行時にJava仮想マシンのデータ領域
1は、実行時データ領域が2つのものを持って、1スレッドのプライベートエリアがあり、プライベートエリアにスレッドを開きます各スレッドは、プログラムカウンタ、仮想マシンのスタックを含み、ローカル方法スタック。別の共有データ領域であり、すべてのスレッドがプールの定常領域を含む方法、ヒープメモリを含む、アクセスすることができる
2は、プログラム・カウンタは、コードの実行の指標である、コードの次のラインの位置を決定するために実行されます。例えば、我々は方法を記述し、この方法は、コードの行数を持っている、プログラムカウンタは、メモリアドレスを実行するために、現在のコードの次の行を記録することです。コードの現在の行の終了が実行された後、プログラムは次の行に私たちを導きます。実行中の複数のスレッドがある場合は、各スレッドは、独自のプログラムカウンタを持っています。地域に存在していないメモリが不足しています。
3、仮想マシン・スタック、店のJavaメソッドは、我々は通常、スタックのこの領域と言います。領域はOOMとstackoverflowのが表示されます。ローカル変数、メソッドがアドレスを返します(メソッド呼び出しの終了後に、リターンアドレスがスタックに戻されますが)機能は何のメモリの断片化(存在しないことの領域に格納されている画像を保存するために連続した収納スペースはの過程で、 、私たちは私たちの写真を削除するには、この絵は、メモリ内で削除された。その後、我々はメッセージを保存する必要がありますが、あなたが望むより少ないメモリスペースを取りません絵があり、これより次の大きな記憶メモリ情報がメモリの一部を空です。この最後尾の連続したメモリ領域に格納されるときに我々は、メモリのこの種が壊れて、長い時間のメモリのブロックを使用する場合、このメモリは、メモリの断片化と呼ばれていますブロック)がたくさんあります
4、ネイティブメソッドスタックはネイティブメソッドの一部を格納します。
図5に示すように、ヒープメモリとメモリリークが容易主記憶メモリのうちおり、インスタンスとオブジェクト(スタックアレイに保存された名前)の配列情報の二種類の内容を発生します。この1は、仮想メモリ管理機能の最大の作品ですGCの主戦場です。
図6に示すように、定数プールは、(パブリック静的最終変性のものを使用して)リテラルの数、定数、文字列(文字[]配列蓄積型)、クラスインターフェース及びメソッドの名前を格納します。
ここに画像を挿入説明
つまり、私たちは、ヒープメモリを最適化することができます。
第三:ガベージコレクションのメカニズムは、メモリの回復を決定する方法である
:GCアルゴリズム
1、および参照カウントアルゴリズムを
、変数1がある場合に行います。私たちは時間のオブジェクトを作成するときに、このようなオブジェクトO1 =新しいオブジェクト()として、すなわち、1 = 1 +カウント;例えば、スタックはメモリ参照に行く必要があります。そして私たちは、次のコードを記述します。
O2オブジェクト;
O2 = O1は、
この時間カウンタは、+ 1 + 1 = 2をカウントします。ヒープを引用した2つの参照があります。私たちは、次のコードを書きます。
O1 = NULL;
カウントが1である、すなわち、1つのカウント= -1;カウンターもO1であるので、この露光時間は、問題、O1のないこの時間、O2回復カウンターになります1;カウント数= 0回復時間がされる場合のみです。このようにして、我々は、メモリの8つのバイトを作成します回復することはできません。
我々はアンドロイドにこのアルゴリズムを適用しない;
2は、到達可能性解析アルゴリズムは、このアルゴリズムは、私たちのアンドロイドを使用することです。
ここに画像を挿入説明

GCのルートオブジェクトとして使用することができ、仮想マシンは、静的プロパティを使用して定数を基準スタックを実行して、JNI参照オブジェクト。
GC 2のみを回復するためにスキャンを必要とするので、私たちは基準の損失節約するためにオブジェクトを確定することができます
ように。

static App a;
@Override
protected void() throws Throwable{
	super.finalize();
	a=this;
}

第四に、Javaの4つの基準
ファントム参照PhantomReference:生存率は影響を及ぼさない、GCを追跡するための通知を思い出します。
弱参照の弱い参照:最初のパスは、マークダウンするために、第2の走査を直接回収されます。また、GCのリコール通知を追跡するために使用することができます

  @Test
    public void testWeakReference() throws InterruptedException {
        ReferenceQueue<Object> referenceQueuee=new ReferenceQueue<>();
        Object weakObject=new Object();
        //弱引用
        WeakReference weakReference=new WeakReference(weakObject,referenceQueuee);
        System.out.println("WeakReference:"+weakReference.get());//Object内存地址
        System.out.println("referenceQueuee:"+referenceQueuee.poll());//null

        weakObject=null;
        System.gc();
        Thread.sleep(2000);
        System.out.println("WeakReference:"+weakReference.get());//null
        System.out.println("referenceQueuee:"+referenceQueuee.poll());//object内存地址
    }



    @Test
    public void testPhantomReference() throws InterruptedException {
        //虚引用:功能,不会影响到对象的生命周期的,
        // 但是能让程序员知道该对象什么时候被 回收了
        ReferenceQueue<Object> referenceQueuee=new ReferenceQueue<>();
        Object phantomObject=new Object();
        PhantomReference phantomReference=new PhantomReference(phantomObject,referenceQueuee);
        phantomObject=null;
        System.out.println("phantomObject:"+phantomObject);//null
        System.out.println("phantomReference"+referenceQueuee.poll());//null
        System.gc();
        Thread.sleep(2000);
        System.out.println("referenceQueuee:"+referenceQueuee.poll());//地址
    }

軟らかい基準SoftReference:メモリ不足のリコールは、いくつかの重要性を保存する非常に強力なものではなく、簡単な背景画像として明確なオブジェクトは、即座に表示するように切り替える必要はありませんすることはできません
第五に:メモリリークが発生
原因:理由1、メモリリークを:短いライフサイクルオブジェクトの長いライフサイクルは、オブジェクトへの参照を保持している
最終的にOOM生成されます、引用問題がリサイクルされていないとして人気の話は、回復の対象となる
のアンドロイドプロファイル使用して、2を
選択し、実行----プロファイルアプリを、それこのツールを開くことができる
かのボタンを選択します。
ここに画像を挿入説明
その後、私たちは、この画面の実行
ここに画像を挿入説明
メモリ上のクリックを、メモリのセクションを選択します。割り当て割り当て解除の合計は(ヒープのインスタンスの数)、浅いサイズ(バイト単位の合計サイズのこのヒープは、すべてのインスタンスを、)カウント。四つのフィールドがあります
最も重要なことは、浅いサイズで、私たちのメモリは、オブジェクト自体によって占め表現するためには、サイズ。
ここに画像を挿入説明

SDKの\プラットフォーム-toolsディレクトリ下の\ HPROF-conv.exe:フォーマット変換ツールDがあります

図3は、最適化:お問い合わせの際に、我々はMainActivity二つの場所はMainActivityにつながる、MainActivityの参照を保持した後、バックグラウンドに切り替えが回復することはできませんが残っていることがわかりました。2つの保持MainActivity参照がmServedViewとmNextServedViewです。どのようにそれを行うには?私たちは、活動中にこれら二つの部材を反映して、onDestroyで間接参照()ですることができます。

 @Override
    protected void onDestroy() {
        unRegisterBroadcastReceiver();
        super.onDestroy();
        method("mServedView");
        method("mNextServedView");
    }

    /**
     * 反射置空输入法中的属性
     * 传入的参数是一个属性,只要调用这个方法,就把这个属性置空。
     */
    public void method(String attr){
        //InputMethodManager:整个输入法框架(IMF)结构的核心API,应用程序之间进行调度和当前输入法交互。
        InputMethodManager im=(InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
        //反射
        try{
            //拿到字段
            Field mCurRootViewField = InputMethodManager.class.getDeclaredField(attr);
            //不是public属性,设置权限
            mCurRootViewField.setAccessible(true);
            //取对象
            Object mCurRootView=mCurRootViewField.get(im);

            if (null!=mCurRootView) {
                Context context=((View)mCurRootView).getContext();
                if(context==this){
                    //破坏GC链
                    mCurRootViewField.set(im,null);
                }
            }
        }catch(Exception e){
            e.printStackTrace();
        }
    }

おすすめ

転載: blog.csdn.net/qczg_wxg/article/details/89786992