什么是内存泄漏和内存溢出?
内存泄漏有什么危害?
LeakCanary检测内存泄漏?
内存泄漏(Memory Leak)和内存溢出(Memory OverFlow)
内存泄漏(Memory Leak)是在指为对象分配了一块内存空间,可是该对象没有引用却一直不释放而导致这块内存一直处在占用状态!换句话说:就是上厕所不冲水。。。一般来说重启机器可以解决这种问题,不过可能会再次出现,这种情况一般都是软件设计的问题!
内存溢出(Memory Overflow)是就是程序为对象分配了N块内存空间,可是该对象却想使用更多的内存!举个栗子:没钱却想环游世界,天真无邪!
两者的危害
1.OOM,outOfMemoryError,
2.过多占用内存导致系统运行变慢,严重可导致ANR
两者区别
- 内存泄漏是导致内存溢出的原因之一,而内存泄漏积累起来就会内存溢出
- 内存泄漏可以通过优化代码来避免,而内存溢出可以调节设备来减少频率,但是没办法完全避免
LeakCanary检测内存泄漏
Github:https://github.com/square/leakcanary
我就介绍一下leakcanary是什么东西吧,其实就是一个可以检测java和Android的第三方框架!那么它是怎么运作的呢?
<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>
以下是百度翻译的结果!
<pre>
refwatcher。watch()创建一个keyedweakreference的观看对象。
稍后,在后台线程中,它检查引用是否已被清除,是否触发了一个气相色谱。
如果参考仍然是不清楚的,然后堆成一堆。HPROF文件存储在文件系统。
heapanalyzerservice是开始在一个单独的进程和HeapAnalyzer分析堆转储使用哈哈。
HeapAnalyzer发现keyedweakreference在堆转储由于独特的参考答案和定位泄漏的参考。
HeapAnalyzer计算最短路径的GC根强引用,以确定是否有泄漏,并建立了泄漏的原因引用链。
其结果是通过回displayleakservice在应用过程中,和泄漏的通知显示。
</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>
不过我们开始着手试试把,反正很简单是吧,我们来看看项目Demo!!嘿嘿嘿~~
<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,当用户旋转手机屏幕,Activity会重新绘制,可是由于当前Activity还在后台线程上面运行,所以Activity对象不会被释放,那么最终的结果也很正常。。
好吧,感谢大家能够听我牢骚那么多!喜欢就点个赞呗!