Android App发生内存泄漏,常见的有Bitmap 使用后沒有recycle(),Drawable 使用后沒有setCallback(null)等。
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
用EclipseOpen 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 Activitya0 ;
private static Activitya1 ;
private static Activitya2 ;
private static Activitya3 ;
private static Activitya4 ;
/*
* Shutdown intent
*/
private final String INTENT_ACTION_REQUEST_SHUTDOWN =
"android.intent.action.ACTION_REQUEST_SHUTDOWN";
@Override
public void onCreate(Bundle savedInstanceState) {
Log.v(TAG, "onCreateActivity="+this);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//1
if(false){
if(a0 == null){
a0 = this;
Log.v(TAG, "onCreateActivity a0="+a0);
}
else if(a1 == null){
a1 = this;
Log.v(TAG, "onCreateActivity a1="+a1);
}
else if(a2 == null){
a2 = this;
Log.v(TAG, "onCreateActivity a2="+a2);
}
else if(a3 == null){
a3 = this;
Log.v(TAG, "onCreateActivity a3="+a3);
}
else if(a4 == null){
a4 = this;
Log.v(TAG, "onCreateActivity 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, "onCreatemBackground1");
mBackground1 = getResources().getDrawable(R.drawable.adbroot_004);
myButton.setBackgroundDrawable(mBackground1);
}
else if(mBackground2 == null){
Log.v(TAG, "onCreatemBackground2");
mBackground2 = getResources().getDrawable(R.drawable.test002);
myButton.setBackgroundDrawable(mBackground2);
}
else if(mBackground3 == null){
Log.v(TAG, "onCreatemBackground3");
mBackground3 = getResources().getDrawable(R.drawable.test003);
myButton.setBackgroundDrawable(mBackground3);
}
else if(mBackground4 == null){
Log.v(TAG, "onCreatemBackground4");
mBackground4 = getResources().getDrawable(R.drawable.adbroot_003);
myButton.setBackgroundDrawable(mBackground4);
}
}