自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Android面試被問(wèn)到內(nèi)存泄漏了雜整?

開(kāi)發(fā) 后端 Android
內(nèi)存泄漏即該被釋放的內(nèi)存沒(méi)有被及時(shí)的釋放,一直被某個(gè)或某些實(shí)例所持有卻不再使用導(dǎo)致GC不能回收。Java程序運(yùn)行時(shí)的內(nèi)存分配策略有三種,分別是靜態(tài)分配,棧式分配,和堆式分配。對(duì)應(yīng)的三種策略使用的內(nèi)存空間是要分別是靜態(tài)存儲(chǔ)區(qū)(也稱(chēng)方法區(qū)),棧區(qū),和堆區(qū)。

[[213752]]

內(nèi)存泄漏即該被釋放的內(nèi)存沒(méi)有被及時(shí)的釋放,一直被某個(gè)或某些實(shí)例所持有卻不再使用導(dǎo)致GC不能回收。

Java內(nèi)存分配策略

Java程序運(yùn)行時(shí)的內(nèi)存分配策略有三種,分別是靜態(tài)分配,棧式分配,和堆式分配。對(duì)應(yīng)的三種策略使用的內(nèi)存空間是要分別是靜態(tài)存儲(chǔ)區(qū)(也稱(chēng)方法區(qū)),棧區(qū),和堆區(qū)。

  • 靜態(tài)存儲(chǔ)區(qū)(方法區(qū)):主要存放靜態(tài)數(shù)據(jù),全局static數(shù)據(jù)和常量。這塊內(nèi)存在程序編譯時(shí)就已經(jīng)分配好,并且在程序整個(gè)運(yùn)行期間都存在。
  • 棧區(qū):當(dāng)方法執(zhí)行時(shí),方法內(nèi)部的局部變量都建立在棧內(nèi)存中,并在方法結(jié)束后自動(dòng)釋放分配的內(nèi)存。因?yàn)闂?nèi)存分配是在處理器的指令集當(dāng)中所以效率很高,但是分配的內(nèi)存容量有限。
  • 堆區(qū):又稱(chēng)動(dòng)態(tài)內(nèi)存分配,通常就是指在程序運(yùn)行時(shí)直接new出來(lái)的內(nèi)存。這部分內(nèi)存在不適用時(shí)將會(huì)由Java垃圾回收器來(lái)負(fù)責(zé)回收。

棧與堆的區(qū)別:

在方法體內(nèi)定義的(局部變量)一些基本類(lèi)型的變量和對(duì)象的引用變量都在方法的棧內(nèi)存中分配。當(dāng)在一段方法塊中定義一個(gè)變量時(shí),Java就會(huì)在棧中為其分配內(nèi)存,當(dāng)超出變量作用域時(shí),該變量也就無(wú)效了,此時(shí)占用的內(nèi)存就會(huì)釋放,然后會(huì)被重新利用。

堆內(nèi)存用來(lái)存放所有new出來(lái)的對(duì)象(包括該對(duì)象內(nèi)的所有成員變量)和數(shù)組。在堆中分配的內(nèi)存,由Java垃圾回收管理器來(lái)自動(dòng)管理。在堆中創(chuàng)建一個(gè)對(duì)象或者數(shù)組,可以在棧中定義一個(gè)特殊的變量,這個(gè)變量的取值等于數(shù)組或?qū)ο笤诙褍?nèi)存中的首地址,這個(gè)特殊的變量就是我們上面提到的引用變量。我們可以通過(guò)引用變量來(lái)訪問(wèn)堆內(nèi)存中的對(duì)象或者數(shù)組。

舉個(gè)例子:

  1. public class Sample {     
  2.     int s1 = 0; 
  3.     Sample mSample1 = new Sample();    
  4.   
  5.     public void method() {         
  6.         int s2 = 0; 
  7.         Sample mSample2 = new Sample(); 
  8.     } 
  9.     Sample mSample3 = new Sample();  

如上局部變量s2和mSample2存放在棧內(nèi)存中,mSample3所指向的對(duì)象存放在堆內(nèi)存中,包括該對(duì)象的成員變量s1和mSample1也存放在堆中,而它自己則存放在棧中。

結(jié)論:

局部變量的基本類(lèi)型和引用存儲(chǔ)在棧內(nèi)存中,引用的實(shí)體存儲(chǔ)在堆中。——因它們存在于方法中,隨方法的生命周期而結(jié)束。

成員變量全部存儲(chǔ)于堆中(包括基本數(shù)據(jù)類(lèi)型,引用和引用的對(duì)象實(shí)體)。——因?yàn)樗鼈儗儆陬?lèi),類(lèi)對(duì)象終究要被new出來(lái)使用。

了解了Java的內(nèi)存分配之后,我們?cè)賮?lái)看看Java是怎么管理內(nèi)存。

Java是如何管理內(nèi)存

由程序分配內(nèi)存,GC來(lái)釋放內(nèi)存。內(nèi)存釋放的原理為該對(duì)象或者數(shù)組不再被引用,則JVM會(huì)在適當(dāng)?shù)臅r(shí)候回收內(nèi)存。

內(nèi)存管理算法:

    1. 引用計(jì)數(shù)法:對(duì)象內(nèi)部定義引用變量,當(dāng)該對(duì)象被某個(gè)引用變量引用時(shí)則計(jì)數(shù)加1,當(dāng)對(duì)象的某個(gè)引用變量超出生命周期或者引用了新的變量時(shí),計(jì)數(shù)減1。任何引用計(jì)數(shù)為0的對(duì)象實(shí)例都可以被GC。這種算法的優(yōu)點(diǎn)是:引用計(jì)數(shù)收集器可以很快的執(zhí)行,交織在程序運(yùn)行中。對(duì)程序需要不被長(zhǎng)時(shí)間打斷的實(shí)時(shí)環(huán)境比較有利。缺點(diǎn):無(wú)法檢測(cè)出循環(huán)引用。

引用計(jì)數(shù)無(wú)法解決的循環(huán)引用問(wèn)題如下:   

  1. public void method() {         
  2.         //Sample count=1 
  3.         Sample ob1 = new Sample();         
  4.         //Sample count=2 
  5.         Sample ob2 = new Sample();         
  6.         //Sample count=3 
  7.         ob1.mSample = ob2;         
  8.         //Sample count=4 
  9.         ob2.mSample = ob1;         
  10.         //Sample count=3 
  11.         ob1=null;         
  12.         //Sample count=2 
  13.         ob2=null;         
  14.         //計(jì)數(shù)為2,不能被GC 
  15.     }  

Java可以作為GC ROOT的對(duì)象有:虛擬機(jī)棧中引用的對(duì)象(本地變量表),方法區(qū)中靜態(tài)屬性引用的對(duì)象,方法區(qū)中常量引用的對(duì)象,本地方法棧中引用的對(duì)象(Native對(duì)象)

    2. 標(biāo)記清除法:從根節(jié)點(diǎn)集合進(jìn)行掃描,標(biāo)記存活的對(duì)象,然后再掃描整個(gè)空間,對(duì)未標(biāo)記的對(duì)象進(jìn)行回收。在存活對(duì)象較多的情況下,效率很高,但是會(huì)造成內(nèi)存碎片。

    3. 標(biāo)記整理算法:同標(biāo)記清除法,只不過(guò)在回收對(duì)象時(shí),對(duì)存活的對(duì)象進(jìn)行移動(dòng)。雖然解決了內(nèi)存碎片的問(wèn)題但是增加了內(nèi)存的開(kāi)銷(xiāo)。

    4. 復(fù)制算法:此方法為克服句柄的開(kāi)銷(xiāo)和解決堆碎片。把堆分為一個(gè)對(duì)象面和多個(gè)空閑面。把存活的對(duì)象copy到空閑面,主要空閑面就變成了對(duì)象面,原來(lái)的對(duì)象面就變成了空閑面。這樣增加了內(nèi)存的開(kāi)銷(xiāo),且在交換過(guò)程中程序會(huì)暫停執(zhí)行。

    5. 分代算法:分代垃圾回收策略,是基于:不同的對(duì)象的生命周期是不一樣的。因此,不同生命周期的對(duì)象可以采取不同的回收算法,以便提高回收效率。

年輕代:

    1. 所有新生成的對(duì)象首先都是存放在年輕代。年輕代的目標(biāo)就是盡可能快速的收集掉那些生命周期短的對(duì)象。

    2. 新生代內(nèi)存按照8:1:1的比例分為一個(gè)eden區(qū)和兩個(gè)survivor(survivor0,survivor1)區(qū)。一個(gè)Eden區(qū),兩個(gè) Survivor區(qū)(一般而言)。大部分對(duì)象在Eden區(qū)中生成。回收時(shí)先將eden區(qū)存活對(duì)象復(fù)制到一個(gè)survivor0區(qū),然后清空eden區(qū),當(dāng)這個(gè)survivor0區(qū)也存放滿(mǎn)了時(shí),則將eden區(qū)和survivor0區(qū)存活對(duì)象復(fù)制到另一個(gè)survivor1區(qū),然后清空eden和這個(gè)survivor0區(qū),此時(shí)survivor0區(qū)是空的,然后將survivor0區(qū)和survivor1區(qū)交換,即保持survivor1區(qū)為空, 如此往復(fù)。

    3. 當(dāng)survivor1區(qū)不足以存放 eden和survivor0的存活對(duì)象時(shí),就將存活對(duì)象直接存放到老年代。若是老年代也滿(mǎn)了就會(huì)觸發(fā)一次Full GC,也就是新生代、老年代都進(jìn)行回收

    4. 新生代發(fā)生的GC也叫做Minor GC,MinorGC發(fā)生頻率比較高(不一定等Eden區(qū)滿(mǎn)了才觸發(fā))

年老代:

    1. 在年輕代中經(jīng)歷了N次垃圾回收后仍然存活的對(duì)象,就會(huì)被放到年老代中。因此,可以認(rèn)為年老代中存放的都是一些生命周期較長(zhǎng)的對(duì)象。

    2. 內(nèi)存比新生代也大很多(大概比例是1:2),當(dāng)老年代內(nèi)存滿(mǎn)時(shí)觸發(fā)Major GC即Full GC,F(xiàn)ull GC發(fā)生頻率比較低,老年代對(duì)象存活時(shí)間比較長(zhǎng),存活率標(biāo)記高。

持久代:

用于存放靜態(tài)文件,如Java類(lèi)、方法等。持久代對(duì)垃圾回收沒(méi)有顯著影響,但是有些應(yīng)用可能動(dòng)態(tài)生成或者調(diào)用一些class,例如Hibernate 等,在這種時(shí)候需要設(shè)置一個(gè)比較大的持久代空間來(lái)存放這些運(yùn)行過(guò)程中新增的類(lèi)。

Android常見(jiàn)的內(nèi)存泄漏匯總

集合類(lèi)泄漏

先看一段代碼   

  1. List<Object> objectList = new ArrayList<>();         
  2.       for (int i = 0; i < 10; i++) { 
  3.            Object o = new Object(); 
  4.            objectList.add(o); 
  5.            o = null
  6.        }  

上面的實(shí)例,雖然在循環(huán)中把引用o釋放了,但是它被添加到了objectList中,所以objectList也持有對(duì)象的引用,此時(shí)該對(duì)象是無(wú)法被GC的。因此對(duì)象如果添加到集合中,還必須從中刪除,最簡(jiǎn)單的方法 

  1. //釋放objectList 
  2.         objectList.clear(); 
  3.         objectList=null; 

單例造成的內(nèi)存泄漏

由于單例的靜態(tài)特性使得其生命周期跟應(yīng)用的生命周期一樣長(zhǎng),所以如果使用不恰當(dāng)?shù)脑?huà),很容易造成內(nèi)存泄漏。比如下面一個(gè)典型的例子。

  1. public class SingleInstanceClass {     
  2.     private static SingleInstanceClass instance;     
  3.     private Context mContext;     
  4.     private SingleInstanceClass(Context context) {         
  5.         this.mContext = context; 
  6.     }   
  7.    
  8.     public SingleInstanceClass getInstance(Context context) {         
  9.         if (instance == null) { 
  10.             instance = new SingleInstanceClass(context); 
  11.         }         
  12.         return instance; 
  13.     } 

正如前面所說(shuō),靜態(tài)變量的生命周期等同于應(yīng)用的生命周期,此處傳入的Context參數(shù)便是禍端。如果傳遞進(jìn)去的是Activity或者Fragment,由于單例一直持有它們的引用,即便Activity或者Fragment銷(xiāo)毀了,也不會(huì)回收其內(nèi)存。特別是一些龐大的Activity非常容易導(dǎo)致OOM。

正確的寫(xiě)法應(yīng)該是傳遞Application的Context,因?yàn)锳pplication的生命周期就是整個(gè)應(yīng)用的生命周期,所以沒(méi)有任何的問(wèn)題。 

  1. public class SingleInstanceClass {     
  2.  
  3.     private static SingleInstanceClass instance;     
  4.  
  5.     private Context mContext;     
  6.  
  7.     private SingleInstanceClass(Context context) {         
  8.  
  9.         this.mContext = context.getApplicationContext();// 使用Application 的context 
  10.  
  11.     }      
  12.  
  13.     public SingleInstanceClass getInstance(Context context) {         
  14.  
  15.         if (instance == null) { 
  16.  
  17.             instance = new SingleInstanceClass(context); 
  18.  
  19.         }         
  20.  
  21.         return instance; 
  22.  
  23.     } 
  24.  
  25.  
  26.  
  27.  
  28. or  
  29.          
  30.  
  31. //在Application中定義獲取全局的context的方法 
  32.  
  33.  /** 
  34.  
  35.      * 獲取全局的context 
  36.  
  37.      * @return 返回全局context對(duì)象 
  38.  
  39.      */ 
  40.  
  41.     public static Context getContext(){         
  42.  
  43.         return context; 
  44.  
  45.     }  
  46.  
  47.  
  48. public class SingleInstanceClass {     
  49.  
  50.     private static SingleInstanceClass instance;     
  51.  
  52.     private Context mContext;     
  53.  
  54.     private SingleInstanceClass() { 
  55.  
  56.        mContext=MyApplication.getContext; 
  57.  
  58.     }     
  59.  
  60.     public SingleInstanceClass getInstance() {         
  61.  
  62.         if (instance == null) { 
  63.  
  64.             instance = new SingleInstanceClass(); 
  65.  
  66.         }         
  67.  
  68.         return instance; 
  69.  
  70.     } 
  71.  
  72.  

匿名內(nèi)部類(lèi)/非靜態(tài)內(nèi)部類(lèi)和異步線(xiàn)程

  • 非靜態(tài)內(nèi)部類(lèi)創(chuàng)建靜態(tài)實(shí)例造成的內(nèi)存泄漏

我們都知道非靜態(tài)內(nèi)部類(lèi)是默認(rèn)持有外部類(lèi)的引用的,如果在內(nèi)部類(lèi)中定義單例實(shí)例,會(huì)導(dǎo)致外部類(lèi)無(wú)法釋放。如下面代碼:

  1. public class TestActivity extends AppCompatActivity {     
  2.     public static InnerClass innerClass = null;  
  3.     
  4.     @Override 
  5.     protected void onCreate(@Nullable Bundle savedInstanceState) {         
  6.         super.onCreate(savedInstanceState);         
  7.         if (innerClass == null
  8.             innerClass = new InnerClass(); 
  9.     }     
  10.     private class InnerClass {         
  11.         //... 
  12.     } 
  13.  

當(dāng)TestActivity銷(xiāo)毀時(shí),因?yàn)閕nnerClass生命周期等同于應(yīng)用生命周期,但是它又持有TestActivity的引用,因此導(dǎo)致內(nèi)存泄漏。

正確做法應(yīng)將該內(nèi)部類(lèi)設(shè)為靜態(tài)內(nèi)部類(lèi)或?qū)⒃搩?nèi)部類(lèi)抽取出來(lái)封裝成一個(gè)單例,如果需要使用Context,請(qǐng)按照上面推薦的使用Application 的 Context。當(dāng)然,Application 的 context 不是***的,所以也不能隨便亂用,對(duì)于有些地方則必須使用 Activity 的 Context,對(duì)于Application,Service,Activity三者的Context的應(yīng)用場(chǎng)景如下:

  • 匿名內(nèi)部類(lèi)

android開(kāi)發(fā)經(jīng)常會(huì)繼承實(shí)現(xiàn)Activity/Fragment/View,此時(shí)如果你使用了匿名類(lèi),并被異步線(xiàn)程持有了,那要小心了,如果沒(méi)有任何措施這樣一定會(huì)導(dǎo)致泄露。如下代碼:

  1. public class TestActivity extends AppCompatActivity {   
  2.     //.... 
  3.  
  4.     private Runnable runnable=new Runnable() {         
  5.         @Override 
  6.         public void run() { 
  7.  
  8.         } 
  9.     };     
  10.     @Override 
  11.     protected void onCreate(@Nullable Bundle savedInstanceState) {         
  12.         super.onCreate(savedInstanceState);        
  13.         //...... 
  14.     } 
  15.  

上面的runnable所引用的匿名內(nèi)部類(lèi)持有TestActivity的引用,當(dāng)將其傳入異步線(xiàn)程中,線(xiàn)程與Activity生命周期不一致就會(huì)導(dǎo)致內(nèi)存泄漏。

  • Handler造成的內(nèi)存泄漏

Handler造成內(nèi)存泄漏的根本原因是因?yàn)椋琀andler的生命周期與Activity或者View的生命周期不一致。Handler屬于TLS(Thread Local Storage)生命周期同應(yīng)用周期一樣??聪旅娴拇a:

  1. public class TestActivity extends AppCompatActivity {     
  2.  
  3.     private Handler mHandler = new Handler() {         
  4.  
  5.         @Override 
  6.  
  7.         public void dispatchMessage(Message msg) {             
  8.  
  9.             super.dispatchMessage(msg); 
  10.  
  11.         } 
  12.  
  13.     };     
  14.  
  15.     @Override 
  16.  
  17.     protected void onCreate(@Nullable Bundle savedInstanceState) {         
  18.  
  19.         super.onCreate(savedInstanceState); 
  20.  
  21.         mHandler.postDelayed(new Runnable() {             
  22.  
  23.             @Override 
  24.  
  25.             public void run() {             
  26.  
  27.             //do your things 
  28.  
  29.             } 
  30.  
  31.         }, 60 * 1000 * 10); 
  32.  
  33.         finish(); 
  34.  
  35.     } 
  36.  
  37.  

在該TestActivity中聲明了一個(gè)延遲10分鐘執(zhí)行的消息 Message,mHandler將其 push 進(jìn)了消息隊(duì)列 MessageQueue 里。當(dāng)該 Activity 被finish()掉時(shí),延遲執(zhí)行任務(wù)的Message 還會(huì)繼續(xù)存在于主線(xiàn)程中,它持有該 Activity 的Handler引用,所以此時(shí) finish()掉的 Activity 就不會(huì)被回收了從而造成內(nèi)存泄漏(因 Handler 為非靜態(tài)內(nèi)部類(lèi),它會(huì)持有外部類(lèi)的引用,在這里就是指TestActivity)。

修復(fù)方法:采用內(nèi)部靜態(tài)類(lèi)以及弱引用方案。代碼如下:

  1. public class TestActivity extends AppCompatActivity {     
  2.  
  3.     private MyHandler mHandler;     
  4.  
  5.     private static class MyHandler extends Handler {         
  6.  
  7.         private final WeakReference<TestActivity> mActivity;         
  8.  
  9.         public MyHandler(TestActivity activity) { 
  10.  
  11.             mActivity = new WeakReference<>(activity); 
  12.  
  13.         }      
  14.  
  15.     
  16.  
  17.         @Override 
  18.  
  19.         public void dispatchMessage(Message msg) {             
  20.  
  21.             super.dispatchMessage(msg); 
  22.  
  23.             TestActivity activity = mActivity.get();             
  24.  
  25.             //do your things 
  26.  
  27.         } 
  28.  
  29.     }     
  30.  
  31. private static final Runnable mRunnable = new Runnable() {         
  32.  
  33.         @Override 
  34.  
  35.         public void run() {             
  36.  
  37.             //do your things 
  38.  
  39.         } 
  40.  
  41.     };     
  42.  
  43.     @Override 
  44.  
  45.     protected void onCreate(@Nullable Bundle savedInstanceState) {         
  46.  
  47.         super.onCreate(savedInstanceState); 
  48.  
  49.         mHandler = new MyHandler(this); 
  50.  
  51.         mHandler.postAtTime(mRunnable, 1000 * 60 * 10); 
  52.  
  53.         finish(); 
  54.  
  55.     } 
  56.  
  57.  

需要注意的是:使用靜態(tài)內(nèi)部類(lèi) + WeakReference 這種方式,每次使用前注意判空。

前面提到了 WeakReference,所以這里就簡(jiǎn)單的說(shuō)一下 Java 對(duì)象的幾種引用類(lèi)型。

Java對(duì)引用的分類(lèi)有 Strong reference, SoftReference, WeakReference, PhatomReference 四種。

ok,繼續(xù)回到主題。前面所說(shuō)的,創(chuàng)建一個(gè)靜態(tài)Handler內(nèi)部類(lèi),然后對(duì) Handler 持有的對(duì)象使用弱引用,這樣在回收時(shí)也可以回收 Handler 持有的對(duì)象,但是這樣做雖然避免了Activity泄漏,不過(guò)Looper 線(xiàn)程的消息隊(duì)列中還是可能會(huì)有待處理的消息,所以我們?cè)贏ctivity的 Destroy 時(shí)或者 Stop 時(shí)應(yīng)該移除消息隊(duì)列 MessageQueue 中的消息。

下面幾個(gè)方法都可以移除 Message:

  1. public final void removeCallbacks(Runnable r); 
  2.  
  3. public final void removeCallbacks(Runnable r, Object token); 
  4.  
  5. public final void removeCallbacksAndMessages(Object token); 
  6.  
  7. public final void removeMessages(int what); 
  8.  
  9. public final void removeMessages(int what, Object object);  

盡量避免使用 staic 成員變量

如果成員變量被聲明為 static,那我們都知道其生命周期將與整個(gè)app進(jìn)程生命周期一樣。

這會(huì)導(dǎo)致一系列問(wèn)題,如果你的app進(jìn)程設(shè)計(jì)上是長(zhǎng)駐內(nèi)存的,那即使app切到后臺(tái),這部分內(nèi)存也不會(huì)被釋放。按照現(xiàn)在手機(jī)app內(nèi)存管理機(jī)制,占內(nèi)存較大的后臺(tái)進(jìn)程將優(yōu)先回收,意味著如果此app做過(guò)進(jìn)程互保保活,那會(huì)造成app在后臺(tái)頻繁重啟。就會(huì)出現(xiàn)一夜時(shí)間手機(jī)被消耗空了電量、流量,這樣只會(huì)被用戶(hù)棄用。

這里修復(fù)的方法是:

不要在類(lèi)初始時(shí)初始化靜態(tài)成員??梢钥紤]lazy初始化。

架構(gòu)設(shè)計(jì)上要思考是否真的有必要這樣做,盡量避免。如果架構(gòu)需要這么設(shè)計(jì),那么此對(duì)象的生命周期你有責(zé)任管理起來(lái)。

  • 避免 override finalize():
  1. finalize 方法被執(zhí)行的時(shí)間不確定,不能依賴(lài)與它來(lái)釋放緊缺的資源。時(shí)間不確定的原因是: 虛擬機(jī)調(diào)用GC的時(shí)間不確定以及Finalize daemon線(xiàn)程被調(diào)度到的時(shí)間不確定。
  2. finalize 方法只會(huì)被執(zhí)行一次,即使對(duì)象被復(fù)活,如果已經(jīng)執(zhí)行過(guò)了 finalize 方法,再次被 GC 時(shí)也不會(huì)再執(zhí)行了,原因是:含有 finalize 方法的 object 是在 new 的時(shí)候由虛擬機(jī)生成了一個(gè) finalize reference 在來(lái)引用到該Object的,而在 finalize 方法執(zhí)行的時(shí)候,該 object 所對(duì)應(yīng)的 finalize Reference 會(huì)被釋放掉,即使在這個(gè)時(shí)候把該 object 復(fù)活(即用強(qiáng)引用引用住該 object ),再第二次被 GC 的時(shí)候由于沒(méi)有了 finalize reference 與之對(duì)應(yīng),所以 finalize 方法不會(huì)再執(zhí)行。
  3. 含有Finalize方法的object需要至少經(jīng)過(guò)兩輪GC才有可能被釋放。

其它 

內(nèi)存泄漏檢測(cè)工具強(qiáng)烈推薦 squareup 的 LeakCannary,但需要注意Android版本是4.4+的,否則會(huì)Crash。 

責(zé)任編輯:龐桂玉 來(lái)源: 安卓巴士Android開(kāi)發(fā)者門(mén)戶(hù)
相關(guān)推薦

2020-09-22 07:49:05

內(nèi)存泄漏

2024-03-06 08:00:56

javaAQS原生

2018-10-31 12:41:11

2023-04-10 09:32:00

DubboJava

2020-09-15 10:25:13

Redis命令Java

2020-10-10 09:01:54

泄漏

2016-03-21 10:31:25

Android內(nèi)存泄露

2016-12-22 17:21:11

Android性能優(yōu)化內(nèi)存泄漏

2023-10-31 16:40:38

LeakCanary內(nèi)存泄漏

2021-04-30 08:21:22

Linux管道設(shè)計(jì)

2016-07-05 14:09:02

AndroidJAVA內(nèi)存

2011-06-01 12:50:41

Android 內(nèi)存

2014-07-30 14:22:41

AndroidWebView內(nèi)存泄漏

2013-08-07 10:16:43

Android內(nèi)存泄漏

2020-04-30 10:24:35

Spring循環(huán)依賴(lài)Java

2023-11-01 16:50:58

2019-11-29 10:16:36

高并發(fā)系統(tǒng)緩存

2013-08-02 09:52:14

AndroidApp內(nèi)存泄漏

2013-02-20 16:02:02

Android開(kāi)發(fā)內(nèi)存泄露

2024-07-03 11:28:15

點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)