Android 3.0+ 内存泄漏检测
1、简介
Android虚拟机的垃圾回收采用的是根搜索算法。GC会从根节点(GC Roots)开始对heap进行遍历。到最后,部分没有直接或者间接引用到GC Roots的就是需要回收的垃圾,会被GC回收掉。而内存泄漏出现的原因就是存在了无效的引用,导致本来需要被GC的对象没有被回收掉,这就造成了内存泄露。
说白了就是有对象没有被回收。
2、简单实例
1)写一个会导致内存泄漏小程序
主要文件
MainActivity.java 实现界面跳转
TwoActivity.java 创建一个延时处理的 handler 程序
当我们跳转到 TwoActivity 界面,紧接着返回主界面, TwoActivity 对象会得不到释放,
因为 handler 会对twoActivity 产生引用。
MainActivity.java
package recognizerdemo.speech.baidu.com.myapplication;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private Button button;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button = (Button) findViewById(R.id.but_id);
button.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.but_id:
Intent intent = new Intent(this,TwoActivity.class);
startActivity(intent);
break;
default:
break;
}
}
}
TwoActivity.java
package recognizerdemo.speech.baidu.com.myapplication;
import android.os.Bundle;
import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
public class TwoActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_two);
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
}
},1000000);
}
}
3、Android Profile 进行内存监控
我们点击了两次 我们可以看到再输出的报告里
TwoActivity 有两个实例
四个参数 的含义:
Heap Dump 右边四列的意思分别如下:
Alloc Count:Java堆中的实例个数
Native Size:native层分配的内存大小。
Shallow Size:Java堆中分配实际大小
Retained Size:这个类的所有实例保留的内存总大小(并非实际大小)
我们单击它,发现右侧出现了Instance View,然后单击Instance View的对象。
在Instance View中,会显示在ActivityOne中的各种对象,而它下方的Reference则是显示诸多对这个存货的ActivityOne对象的引用。大部分都是系统层面的引用,只有一个格外显眼,就是通过“this”对ActivityOne的引用,点进去我们可以发现是MessageQueue持有了这个引用,可以定位到是Handler的内存泄漏了。
4、正常情况下测试内存
1)我们修改TwoActivity.java 代码,不做任何事情
public class TwoActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_two);
/* new Handler().postDelayed(new Runnable() {
@Override
public void run() {
}
},1000000);*/
}
}
2)重新检测一下内存
我们可以发现再内存监控中 根本没有找到 TwoActivity 对象的存在,已经被完全回收。
所以当我们使用内存监控,发现哪个对象数据异常的时候,就可以定位到了泄露的原因。
文献参考:
基于Android Studio的内存泄漏检测与解决全攻略
https://blog.****.net/jinhui157/article/details/73863314
(Android Studio 3.0)Android Profiler内存泄漏检查
https://blog.****.net/Double2hao/article/details/78784758
Android性能优化之Android Device Monitor使用
https://blog.****.net/my_rabbit/article/details/79831911
内存泄露:分析及工具使用
https://blog.****.net/zeqiao/article/details/77334522