Eclipse 有个插件工具MAT(Memory Analyzer Tool)可以帮助定位内存泄漏的对象。
- 安装MAT Update site: http://archive.eclipse.org/mat/1.1/update-site/
- 用DDMS工具Dump出问题App的.hprof文件 比如com.world.test2.hprof Dump之前最好先运行一下GC "Cause GC" , 确保dump出来的是还不能回收的对象等。
- 用SDK tools下工具hprof-conv.exe 做转换 hprof-conv com.world.test2.hprof appleak.hprof
- 用Eclipse “Open Head Dump”打开新转换的.hprof 文件--appleak.hprof 查看图形化界面,一个一个检查怀疑的点。
总结: MAT tool不会直接告诉你哪里内存泄漏,但是会列出怀疑的对象,需要你仔细检查这些对象为什么没有被释放掉。
下面是测试code, 在Android 4.2.2上测试过。 1. 此种情况可以引起Activity无法回收的情况,因为直接用类似private static Activity a0引用创建的Activity,导致Activity无法回收。 2. 此种情况没有引起Activity 无法回收的情况。 按理说这种情况应该也会导致静态Drawable 锁定Activity, 引用关系mBackground1-->Button-->Activity. 待分析
public class MainActivity extends Activity implements Button.OnClickListener{
final private static String TAG = "MainActivity";
private static Drawable mBackground1;
private static Drawable mBackground2;
private static Drawable mBackground3;
private static Drawable mBackground4;
private static Activity a0 ;
private static Activity a1 ;
private static Activity a2 ;
private static Activity a3 ;
private static Activity a4 ;
/*
* Shutdown intent
*/
private final String INTENT_ACTION_REQUEST_SHUTDOWN =
"android.intent.action.ACTION_REQUEST_SHUTDOWN";
@Override
public void onCreate(Bundle savedInstanceState) {
Log.v(TAG, "onCreate Activity="+this);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//1
if(false){
if(a0 == null){
a0 = this;
Log.v(TAG, "onCreate Activity a0="+a0);
}
else if(a1 == null){
a1 = this;
Log.v(TAG, "onCreate Activity a1="+a1);
}
else if(a2 == null){
a2 = this;
Log.v(TAG, "onCreate Activity a2="+a2);
}
else if(a3 == null){
a3 = this;
Log.v(TAG, "onCreate Activity a3="+a3);
}
else if(a4 == null){
a4 = this;
Log.v(TAG, "onCreate Activity a4="+a4);
}
}
//set up button listener
Button myButton = (Button)findViewById(R.id.button_poweroff);
myButton.setOnClickListener(this);
myButton = (Button)findViewById(R.id.button_reboot);
myButton.setOnClickListener(this);
//2
if (mBackground1 == null) {
Log.v(TAG, "onCreate mBackground1");
mBackground1 = getResources().getDrawable(R.drawable.adbroot_004);
myButton.setBackgroundDrawable(mBackground1);
}
else if(mBackground2 == null){
Log.v(TAG, "onCreate mBackground2");
mBackground2 = getResources().getDrawable(R.drawable.test002);
myButton.setBackgroundDrawable(mBackground2);
}
else if(mBackground3 == null){
Log.v(TAG, "onCreate mBackground3");
mBackground3 = getResources().getDrawable(R.drawable.test003);
myButton.setBackgroundDrawable(mBackground3);
}
else if(mBackground4 == null){
Log.v(TAG, "onCreate mBackground4");
mBackground4 = getResources().getDrawable(R.drawable.adbroot_003);
myButton.setBackgroundDrawable(mBackground4);
}
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
- 22.
- 23.
- 24.
- 25.
- 26.
- 27.
- 28.
- 29.
- 30.
- 31.
- 32.
- 33.
- 34.
- 35.
- 36.
- 37.
- 38.
- 39.
- 40.
- 41.
- 42.
- 43.
- 44.
- 45.
- 46.
- 47.
- 48.
- 49.
- 50.
- 51.
- 52.
- 53.
- 54.
- 55.
- 56.
- 57.
- 58.
- 59.
- 60.
- 61.
- 62.
- 63.
- 64.
- 65.
- 66.
- 67.
- 68.
- 69.
- 70.
- 71.
- 72.
- 73.
- 74.
- 75.
- 76.
- 77.
- 78.
- 79.
- 80.
- 81.
- 82.
- 83.
- 84.
- 85.
- 86.
- 87.
- 88.
- 89.
- 90.
- 91.
- 92.
- 93.
- 94.
- 95.
- 96.
- 97.
- 98.
- 99.
- 100.
- 101.
- 102.
- 103.
- 104.
- 105.
- 106.
- 107.
- 108.
- 109.
- 110.
- 111.
- 112.
- 113.
- 114.
- 115.
- 116.
- 117.
- 118.
- 119.
- 120.
- 121.
- 122.
- 123.
- 124.
- 125.
- 126.
- 127.
- 128.
- 129.
- 130.
- 131.
- 132.
- 133.
- 134.
- 135.
- 136.
- 137.
- 138.
- 139.
- 140.
- 141.
- 142.
- 143.
- 144.
- 145.
- 146.
- 147.
- 148.
- 149.
- 150.
- 151.
- 152.
- 153.
- 154.
- 155.
- 156.
- 157.
- 158.
- 159.
- 160.
- 161.
- 162.
- 163.
- 164.
- 165.
- 166.
- 167.
- 168.
- 169.
- 170.