本文共 8142 字,大约阅读时间需要 27 分钟。
内存泄漏也称作“存储渗漏”,用动态存储分配函数动态开辟的空间,在使用完毕后未释放,结果导致一直占据该内存单元。直到程序结束。(其实说白了就是该内存空间使用完毕之后未回收)即所谓内存泄漏。
内存泄漏形象的比喻是“操作系统可提供给所有进程的存储空间正在被某个进程榨干”,最终结果是程序运行时间越长,占用存储空间越来越多,最终用尽全部存储空间,整个系统崩溃。所以“内存泄漏”是从操作系统的角度来看的。这里的存储空间并不是指物理内存,而是指虚拟内存大小,这个虚拟内存大小取决于磁盘交换区设定的大小。由程序申请的一块内存,如果没有任何一个指针指向它,那么这块内存就泄漏了。
——来自《百度百科》
IO
Context
Service
慎用Context
类型 | 垃圾回收时间 | 生存时间 |
---|---|---|
强引用 | 永远不会 | JVM停止运行时终止 |
软引用 | 内存不足时 | 内存不足时终止 |
弱引用 | 垃圾回收时 | 垃圾回收时终止 |
虚引用 | 垃圾回收时 | 垃圾回收时终止 |
复用ConvertView
对象释放
.penaltyLog()
.build());Bitmap泄露一般会泄露较多内存,视图片大小、位图而定
@Override protected void onDestroy() { // TODO Auto-generated method stub super.onDestroy(); recycleImageView(imgv_load_ad); } public static void recycleImageView(View view){ if(view==null) return; if(view instanceof ImageView){ Drawable drawable=((ImageView) view).getDrawable(); if(drawable instanceof BitmapDrawable){ Bitmap bmp = ((BitmapDrawable)drawable).getBitmap(); if (bmp != null && !bmp.isRecycled()){ ((ImageView) view).setImageBitmap(null); bmp.recycle(); bmp=null; } } } }
`
public static void copyFile(File source, File dest) {
FileChannel inChannel = null; FileChannel outChannel = null; Log.i(TAG, "source path: " + source.getAbsolutePath()); Log.i(TAG, "dest path: " + dest.getAbsolutePath()); try { inChannel = new FileInputStream(source).getChannel(); outChannel = new FileOutputStream(dest).getChannel(); inChannel.transferTo(0, inChannel.size(), outChannel); } catch (IOException e) { e.printStackTrace(); } }- 解决方案: - 及时关闭IO流,避免泄露
public static void copyFile(File source, File dest) {
FileChannel inChannel = null; FileChannel outChannel = null; Log.i(TAG, "source path: " + source.getAbsolutePath()); Log.i(TAG, "dest path: " + dest.getAbsolutePath()); try { inChannel = new FileInputStream(source).getChannel(); outChannel = new FileOutputStream(dest).getChannel(); inChannel.transferTo(0, inChannel.size(), outChannel); } catch (IOException e) { e.printStackTrace(); } finally { if (inChannel != null) { try { inChannel.close(); } catch (IOException e) { e.printStackTrace(); } } if (outChannel != null) { try { outChannel.close(); } catch (IOException e) { e.printStackTrace(); } } } }E/StrictMode: A resource was acquired at attached stack trace but never released.
See java.io.Closeable for information on avoiding resource leaks.java.lang.Throwable: Explicit termination method 'close' not called at dalvik.system.CloseGuard.open(CloseGuard.java:180) at java.io.FileOutputStream.(FileOutputStream.java:89) at java.io.FileOutputStream.(FileOutputStream.java:72) at com.heyniu.lock.utils.FileUtil.copyFile(FileUtil.java:44) at com.heyniu.lock.db.BackupData.backupData(BackupData.java:89) at com.heyniu.lock.ui.HomeActivity$11.onClick(HomeActivity.java:675) at android.support.v7.app.AlertController$ButtonHandler.handleMessage(AlertController.java:157) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:148) at android.app.ActivityThread.main(ActivityThread.java:5417) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)### **单例模式泄露**- 分析:通过截图我们发现SplashActivity被ActivityUtil的实例activityStack持有- 引用代码: ActivityUtil.getAppManager().add(this);- 持有代码:
public void add(Activity activity) {
if (activityStack == null) { synchronized (ActivityUtil.class){ if (activityStack == null) { activityStack = new Stack<>(); } } } activityStack.add(activity); }- 解决方案:- 在SplashActivity的onDestroy()生命周期移除引用 ```@Override protected void onDestroy() { super.onDestroy(); ActivityUtil.getAppManager().remove(this); } ``` ![image](https://yqfile.alicdn.com/1998bcf9cd08cdac7d473153af1a2618ef7acd4c.png)### **静态变量持有Context实例泄露**- 分析:长生命周期持有短什么周期引用导致泄露,详见上文四大组件Context和Application的context使用- 示例引用代码:
private static HttpRequest req;
public static void HttpUtilPost(Context context, int TaskId, String url, String requestBody,ArrayList Headers, RequestListener listener) { // TODO Auto-generated constructor stub req = new HttpRequest(context, url, TaskId, requestBody, Headers, listener); req.post(); }- 解决方案:
}
private static WeakReference req;public static void HttpUtilPost(Context context, int TaskId, String url, String requestBody,ArrayList Headers, RequestListener listener) { // TODO Auto-generated constructor stub req = new WeakReference(new HttpRequest(context, url, TaskId, requestBody, Headers, listener)); req.get().post(); }private static HttpRequest req;public static void HttpUtilPost(Context context, int TaskId, String url, String requestBody,ArrayList Headers, RequestListener listener) { // TODO Auto-generated constructor stub req = new HttpRequest(context.getApplicationContext(), url, TaskId, requestBody, Headers, listener); req.post(); }- 改为长生命周期- 改为弱引用- pass:弱引用随时可能为空,使用前先判空- 示例代码: ![image](https://yqfile.alicdn.com/5a2b696c2306c1c4fe5916cce33a6b62feea4687.png) ### **服务未解绑注册泄露**- 分析:一般发生在注册了某服务,不用时未解绑服务导致泄露- 引用代码:
private void initSensor() {
// 获取传感器管理器 sm = (SensorManager) container.activity.getSystemService(Context.SENSOR_SERVICE); // 获取距离传感器 acceleromererSensor = sm.getDefaultSensor(Sensor.TYPE_PROXIMITY); // 设置传感器监听器 acceleromererListener = new SensorEventListener() { ...... }; sm.registerListener(acceleromererListener, acceleromererSensor, SensorManager.SENSOR_DELAY_NORMAL); }- 解决方案: 在Activity的onDestroy()方法解绑服务 ```@Override protected void onDestroy() { super.onDestroy(); sm.unregisterListener(acceleromererListener,acceleromererSensor); }
handler.sendEmptyMessage(0);
解决方案:
在Activity的onDestroy()方法回收Handler
@Override protected void onDestroy() { super.onDestroy(); handler.removeCallbacksAndMessages(null); }
new Thread() { public void run() { imageArray = loadImageFromUrl(imageUrl); }.start();
解决方案:
把线程作为对象提取出来在Activity的onDestroy()方法阻塞线程
thread = new Thread() { public void run() { imageArray = loadImageFromUrl(imageUrl); }; thread.start();@Override protected void onDestroy() { super.onDestroy(); if(thread != null){ thread.interrupt(); thread = null; } }
未完待续。。。
阿里云测移动质量中心(以下简称MQC)是为广大企业客户和移动开发者提供真机测试服务的云平台,拥有大量热门机型,提供7x24全天候服务。 我们致力于提供专业、稳定、全面、高价值的自动化测试能力,以及简单易用的使用流程、贴心的技术服务,并且帮助客户以最低的成本、最高的效率发现APP中的各类隐患(APP崩溃、各类兼容性问题、功能性问题、性能问题等),减少用户流失,提高APP质量和市场竞争力。联系我们:
网站地址: 开发者交流旺旺群:335334143 开发者交流QQ群:492028798 客服邮箱:mqc_group@service.alibaba.com更多精彩技术分享 欢迎关注 MQC公众号转载地址:http://gcqaa.baihongyu.com/