什么是內(nèi)存泄漏和內(nèi)存溢出颜曾?
內(nèi)存泄漏有什么危害?
LeakCanary檢測內(nèi)存泄漏?
內(nèi)存泄漏(Memory Leak)和內(nèi)存溢出(Memory OverFlow)
內(nèi)存泄漏(Memory Leak)是在指為對(duì)象分配了一塊內(nèi)存空間,可是該對(duì)象沒有引用卻一直不釋放而導(dǎo)致這塊內(nèi)存一直處在占用狀態(tài)!換句話說:就是上廁所不沖水欠拾。。骗绕。一般來說重啟機(jī)器可以解決這種問題藐窄,不過可能會(huì)再次出現(xiàn),這種情況一般都是軟件設(shè)計(jì)的問題酬土!
內(nèi)存溢出(Memory Overflow)是就是程序?yàn)閷?duì)象分配了N塊內(nèi)存空間荆忍,可是該對(duì)象卻想使用更多的內(nèi)存!舉個(gè)栗子:沒錢卻想環(huán)游世界撤缴,天真無邪刹枉!
兩者的危害
1.OOM,outOfMemoryError屈呕,
2.過多占用內(nèi)存導(dǎo)致系統(tǒng)運(yùn)行變慢微宝,嚴(yán)重可導(dǎo)致ANR
兩者區(qū)別
- 內(nèi)存泄漏是導(dǎo)致內(nèi)存溢出的原因之一,而內(nèi)存泄漏積累起來就會(huì)內(nèi)存溢出
- 內(nèi)存泄漏可以通過優(yōu)化代碼來避免虎眨,而內(nèi)存溢出可以調(diào)節(jié)設(shè)備來減少頻率蟋软,但是沒辦法完全避免
LeakCanary檢測內(nèi)存泄漏
Github:https://github.com/square/leakcanary
我就介紹一下leakcanary是什么東西吧镶摘,其實(shí)就是一個(gè)可以檢測java和Android的第三方框架!那么它是怎么運(yùn)作的呢岳守?
<pre>
1.RefWatcher.watch() creates a KeyedWeakReference to the watched object.
2.Later, in a background thread, it checks if the reference has been cleared and if not it triggers a GC.
3.If the reference is still not cleared, it then dumps the heap into a .hprof file stored on the file system.
4.HeapAnalyzerService is started in a separate process and HeapAnalyzer parses the heap dump using HAHA.
5.HeapAnalyzer finds the KeyedWeakReference in the heap dump thanks to a unique reference key and locates the leaking reference.
6.HeapAnalyzer computes the shortest strong reference path to the GC Roots to determine if there is a leak, and then builds the chain of references causing the leak.
7.The result is passed back to DisplayLeakService in the app process, and the leak notification is shown.
</pre>
以下是百度翻譯的結(jié)果凄敢!
<pre>
refwatcher。watch()創(chuàng)建一個(gè)keyedweakreference的觀看對(duì)象湿痢。
稍后涝缝,在后臺(tái)線程中,它檢查引用是否已被清除蒙袍,是否觸發(fā)了一個(gè)氣相色譜俊卤。
如果參考仍然是不清楚的,然后堆成一堆害幅。HPROF文件存儲(chǔ)在文件系統(tǒng)。
heapanalyzerservice是開始在一個(gè)單獨(dú)的進(jìn)程和HeapAnalyzer分析堆轉(zhuǎn)儲(chǔ)使用哈哈岂昭。
HeapAnalyzer發(fā)現(xiàn)keyedweakreference在堆轉(zhuǎn)儲(chǔ)由于獨(dú)特的參考答案和定位泄漏的參考以现。
HeapAnalyzer計(jì)算最短路徑的GC根強(qiáng)引用,以確定是否有泄漏约啊,并建立了泄漏的原因引用鏈邑遏。
其結(jié)果是通過回displayleakservice在應(yīng)用過程中,和泄漏的通知顯示恰矩。
</pre>
LeakCanary的使用方式
<pre>
在build.gradle里面添加依賴
dependencies {
debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5'
releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'
testCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'
}
在自己的Application類里面添加
public class ExampleApplication extends Application {
@Override public void onCreate() {
super.onCreate();
if (LeakCanary.isInAnalyzerProcess(this)) {
// This process is dedicated to LeakCanary for heap analysis.
// You should not init your app in this process.
return;
}
LeakCanary.install(this);
// Normal app init code...
}
}
</pre>
不過我們開始著手試試把记盒,反正很簡單是吧,我們來看看項(xiàng)目DemoM飧怠纪吮!嘿嘿嘿~~
<pre>
public class LeakActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
}
@OnClick(R.id.fab)
public void doTask(){
startAsyncTask();
}
void startAsyncTask() {
// This async task is an anonymous class and therefore has a hidden reference to the outer
// class MainActivity. If the activity gets destroyed before the task finishes (e.g. rotation),
// the activity instance will leak.
new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... params) {
// Do some slow work in background
SystemClock.sleep(20000);
return null;
}
}.execute();
}
}
</pre>
okay,當(dāng)用戶旋轉(zhuǎn)手機(jī)屏幕萎胰,Activity會(huì)重新繪制碾盟,可是由于當(dāng)前Activity還在后臺(tái)線程上面運(yùn)行,所以Activity對(duì)象不會(huì)被釋放技竟,那么最終的結(jié)果也很正常冰肴。。
好吧榔组,感謝大家能夠聽我牢騷那么多熙尉!喜歡就點(diǎn)個(gè)贊唄!