三棒旗、內(nèi)存管理

一、java內(nèi)存模型

1.程序計數(shù)器pc-----線程私有

占用內(nèi)存很信蟊帷;java的多線程是:搶占式的
java中程序計數(shù)器pc為:虛擬機(jī)字節(jié)碼地址窜骄;
native中程序計數(shù)器為:undefined 也就是null锦募;

java虛擬機(jī)規(guī)范中沒有定義此區(qū)域有oom

2.虛擬機(jī)棧-----線程私有

java虛擬機(jī)規(guī)范中定義了兩種異常
stackOverflow
oom內(nèi)存溢出
包含:局部變量表,操作棧邻遏,方法返回地址糠亩,動態(tài)鏈接,額外附加信息准验;

3.本地方法棧-----線程私有(Native Method Stack)
和虛擬機(jī)棧差不多赎线,一個是Java虛擬機(jī)的,一個是native層的

java虛擬機(jī)規(guī)范中定義了兩種異常
stackOverflow
oom內(nèi)存溢出

備注:在有些jvm的實現(xiàn)中糊饱,將本地方法棧和虛擬機(jī)棧合二為一了(代表:sun公司的hotpost虛擬機(jī))垂寥;


4.java堆-----數(shù)據(jù)共享區(qū)
虛擬機(jī)管理的最大一塊內(nèi)存。GC的主戰(zhàn)場(垃圾堆)另锋,有oom異常滞项;
5.方法區(qū)-----數(shù)據(jù)共享區(qū)
包含:常量,靜態(tài)變量砰蠢,類信息蓖扑,即使編譯后的java代碼唉铜,特殊的class類台舱,運(yùn)行時常量池(字面量:java的常量,包括一些public static final,符號引用:類+接口 字段名 方法名 描述符)

java內(nèi)存模型.png
二竞惋、引用類型

強(qiáng)軟弱虛
強(qiáng):Object object= new Object();
軟:有用柜去,但不是必須的對象,在內(nèi)存不足的時候拆宛,會將軟引用回收嗓奢;
弱:非必須對象,gc掃過就會回收浑厚;
虛:幽靈引用股耽,不會對生存造成任何影響;沒有辦法得到引用的對象钳幅,但是在對象在回收的時候物蝙,能夠得到通知;
備注:
1.避免OOM----->使用軟引用
2.內(nèi)存得到及時的釋放或回收敢艰;節(jié)省內(nèi)存----->使用弱引用

Object obj = new Object();
        //引用隊列诬乞,當(dāng)保存的對象被gc回收時,可以得到回收的引用對象
        ReferenceQueue<Object> objectReferenceQueue = new ReferenceQueue<>();
        SoftReference<Object> objectSoftReference = new SoftReference<>(obj,objectReferenceQueue);

        //得到保存的對象
        Object o = objectSoftReference.get();
        System.out.println("soft obj:"+o);
        obj = null ;
        //執(zhí)行g(shù)c不能立即執(zhí)行回收钠导,只是通知gc進(jìn)行掃描震嫉;
        System.gc();
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        //當(dāng)內(nèi)存不足時,可以使用objectReferenceQueue.poll()得到引用的對象
        //內(nèi)存不足時使用牡属,可以得到票堵;如果人為的將obj賦值為null,則得不到
        Reference<?> poll = objectReferenceQueue.poll();
        System.out.println("soft queue:"+poll);
        //soft obj:java.lang.Object@2df08e
        //soft queue:null逮栅;不為null代表被回收了

ReferenceQueue不為null换衬,代表被回收了;

三证芭、內(nèi)存泄露

內(nèi)存泄露的根本原因:長生命周期的對象擁有短生命周期對象的引用瞳浦,短生命周期對象無法被回收;也就是該被回收的對象因為引用問題無法被回收废士;

1.Alloc Count :申請內(nèi)存的次數(shù)叫潦,也就是申請的對象數(shù);
2.Shallow Size:對象占用的內(nèi)存大泄傧酢矗蕊;
3.Retained Size:對象引用組占用的大小氢架;

4.轉(zhuǎn)換mat標(biāo)準(zhǔn)文件
轉(zhuǎn)換工具目錄在/SDK/platform-tools/下面

hprof-conv -z src dst :將src轉(zhuǎn)換為dst
例如:hprof-conv -z 1.hprof 1_mat.hprof

5.系統(tǒng)輸入法內(nèi)存泄露bug:
InputMethodManager ----內(nèi)部類持有->mCurRootView---->也就是系統(tǒng)的DecorView---->這個DecorView持有mContext上下文對象傻咖;

解決方法:

 @Override
    protected void onDestroy() {
        super.onDestroy();

        //去除系統(tǒng)級別的輸入法造成的內(nèi)存泄露
        /**
         * InputMethodManager ----內(nèi)部類持有->mCurRootView---->也就是系統(tǒng)的DecorView---->這個DecorView持有mContext上下文對象;
         *
         * 這里可以把InputMethodManager看作是GCRoot岖研,只有打斷這條鏈卿操,才能釋放mCurRootView持有的上下文對象警检;
         * 因為無法直接獲取InputMethodMananger中的mCurRootView對象,只有使用反射來獲取
         */
        InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
        Class<? extends InputMethodManager> aClass = inputMethodManager.getClass();
        try {
            //getDeclaredField() 獲取全部的屬性(不包含繼承所得屬性)     getField()只能獲取public修飾的屬性(包含繼承所得)
            Field mCurRootViewField = aClass.getDeclaredField("mCurRootView");
            mCurRootViewField.setAccessible(true);
            Object mCurRootView = mCurRootViewField.get(inputMethodManager);
            if (null != mCurRootView) {
                Context context = ((View) mCurRootView).getContext();
                if (context == this) {
                    //破壞gc引用鏈
                    mCurRootViewField.set(inputMethodManager,null);
                }
            }
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }

    }

5.檢查內(nèi)存泄露 除了使用mat 還有使用LeakCanary工具害淤;

6.如何防止單例模式內(nèi)存泄露扇雕?
如果必須傳入Activity的上下文對象,可以使用弱引用來持有窥摄,便于及時被gc回收镶奉;
如果非必須 可以使用application的上下文對象;

7.IO操作如何防止內(nèi)存泄露崭放?
在IO操作中哨苛,必須要在finally中進(jìn)行資源的關(guān)閉和釋放;

8.Handler或Thread引起的內(nèi)存泄露币砂?
主要由于使用內(nèi)部類的原因(非靜態(tài)內(nèi)部類持有外部類的引用)移国;
解決方式:使用靜態(tài)內(nèi)部類+弱引用方式;


image.png

創(chuàng)建一個靜態(tài)Handler內(nèi)部類道伟,然后對Handler持有的對象使用弱引用迹缀,這樣在回收時也可以回收Handler持有的對象,這樣雖然避免了Activity泄漏蜜徽,不過Looper線程的消息隊列中還是可能會有待處理的消息祝懂,所以我們在Activity的Destroy時或者Stop時應(yīng)該移除消息隊列中的消息,


image.png

使用mHandler.removeCallbacksAndMessages(null);是移除消息隊列中所有消息和所有的Runnable拘鞋。當(dāng)然也可以使用mHandler.removeCallbacks();或mHandler.removeMessages();來移除指定的Runnable和Message砚蓬。

Thread的內(nèi)存泄露和Handler一樣,處理方式也是一樣的盆色;Thread內(nèi)存泄露的主要原因是因為線程生命周期的不可控灰蛙。比如線程是 Activity 的內(nèi)部類,則線程對象中保存了 Activity 的一個引用隔躲,當(dāng)線程的 run 函數(shù)耗時較長沒有結(jié)束時摩梧,線程對象是不會被銷毀的,因此它所引用的老的 Activity 也不會被銷毀宣旱,因此就出現(xiàn)了內(nèi)存泄露的問題仅父。

9.集合類產(chǎn)生的內(nèi)存泄露?
集合類如果僅僅有添加元素的方法浑吟,而沒有相應(yīng)的刪除機(jī)制笙纤,導(dǎo)致內(nèi)存被占用。如果這個集合類是全局性的變量 (比如類中的靜態(tài)屬性组力,全局性的 map 等即有靜態(tài)引用或 final 一直指向它)省容,那么沒有相應(yīng)的刪除機(jī)制,很可能導(dǎo)致集合所占用的內(nèi)存只增不減燎字。

10.靜態(tài)成員引起的內(nèi)存泄露腥椒?
Static成員作為gc root阿宅,如果一個對象被static聲明,這個對象會一直存活直到程序進(jìn)程停止寞酿。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末家夺,一起剝皮案震驚了整個濱河市脱柱,隨后出現(xiàn)的幾起案子伐弹,更是在濱河造成了極大的恐慌,老刑警劉巖榨为,帶你破解...
    沈念sama閱讀 211,496評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件惨好,死亡現(xiàn)場離奇詭異,居然都是意外死亡随闺,警方通過查閱死者的電腦和手機(jī)日川,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,187評論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來矩乐,“玉大人龄句,你說我怎么就攤上這事∩⒑保” “怎么了分歇?”我有些...
    開封第一講書人閱讀 157,091評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長欧漱。 經(jīng)常有香客問我职抡,道長,這世上最難降的妖魔是什么误甚? 我笑而不...
    開封第一講書人閱讀 56,458評論 1 283
  • 正文 為了忘掉前任缚甩,我火速辦了婚禮,結(jié)果婚禮上窑邦,老公的妹妹穿的比我還像新娘擅威。我一直安慰自己,他們只是感情好冈钦,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,542評論 6 385
  • 文/花漫 我一把揭開白布裕寨。 她就那樣靜靜地躺著,像睡著了一般派继。 火紅的嫁衣襯著肌膚如雪宾袜。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,802評論 1 290
  • 那天驾窟,我揣著相機(jī)與錄音庆猫,去河邊找鬼。 笑死绅络,一個胖子當(dāng)著我的面吹牛月培,可吹牛的內(nèi)容都是我干的嘁字。 我是一名探鬼主播,決...
    沈念sama閱讀 38,945評論 3 407
  • 文/蒼蘭香墨 我猛地睜開眼杉畜,長吁一口氣:“原來是場噩夢啊……” “哼纪蜒!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起此叠,我...
    開封第一講書人閱讀 37,709評論 0 266
  • 序言:老撾萬榮一對情侶失蹤纯续,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后灭袁,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體猬错,經(jīng)...
    沈念sama閱讀 44,158評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,502評論 2 327
  • 正文 我和宋清朗相戀三年茸歧,在試婚紗的時候發(fā)現(xiàn)自己被綠了倦炒。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,637評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡软瞎,死狀恐怖逢唤,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情涤浇,我是刑警寧澤鳖藕,帶...
    沈念sama閱讀 34,300評論 4 329
  • 正文 年R本政府宣布,位于F島的核電站芙代,受9級特大地震影響吊奢,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜纹烹,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,911評論 3 313
  • 文/蒙蒙 一页滚、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧铺呵,春花似錦裹驰、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,744評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至音念,卻和暖如春沪饺,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背闷愤。 一陣腳步聲響...
    開封第一講書人閱讀 31,982評論 1 266
  • 我被黑心中介騙來泰國打工整葡, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人讥脐。 一個月前我還...
    沈念sama閱讀 46,344評論 2 360
  • 正文 我出身青樓遭居,卻偏偏與公主長得像啼器,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子俱萍,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,500評論 2 348

推薦閱讀更多精彩內(nèi)容

  • iPhone 4 以前 2007年端壳,初代iPhone發(fā)布,屏幕的寬高是 320 x 480 像素枪蘑。下文也是按照寬度...
    charlotte2018閱讀 10,001評論 3 14
  • 兒子的游泳課因前段時間下雨损谦,休息,今天才上完第七節(jié)課腥寇,但他還無法解開身上的浮板成翩,另兩位一起學(xué)的小朋友已經(jīng)可以游玩自...
    rainbow33666閱讀 208評論 1 2