美文网首页JAVA
说说内存泄漏?

说说内存泄漏?

作者: Joseph_L | 来源:发表于2019-11-17 21:36 被阅读0次

一般什么情况下会导致内存泄漏问题?

基本知识储备
  • 内存泄漏

    程序不再使用对象 A,但是因为 A 持有另外一个生命周期更长的对象 B 的引用,导致 A 不能及时被回收,一直占用着内存

  • 内存溢出

    内存泄漏情况严重,因为占用情况导致无法被回收的对象越来越多,直到程序对内存的总需求超过了系统给分配的内存空间大小

  • Java 垃圾回收机制(待填坑)

总结来说,只需要记住一点:长生命周期的对象持有短生命周期对象的引用,就会导致内存泄漏;过多的内存泄漏,就会导致内存溢出。

Android 中常见的内存泄漏场景
  • 类的静态变量

    静态变量生命周期与应用相当,Activity 中一个静态的 View 有可能以 new View(this) 的方式持有 Activity 的引用,这种情况会导致对应的 Activity 永远不能被正确回收

  • 内部类持有外部类引用

    • 匿名内部类

      当匿名内部类和异步任务一起出现时,可能发生内存泄漏。当 Activity 关闭时,如果子线程的异步任务还没有完成,那对应的 Activity 就会泄漏

    • 非静态内部类

      常见的就是 Handler 的错误使用。

      public Handler mHandler = new Handler(){
        public void handleMessage(Message msg){}
      }
      

      Handler 持有当前 Activity 引用,它发出的 Message 又持有 Handler 的引用,消息队列持有 Message 的引用,一层套一层,导致 Activity 在关闭后也不能被释放,就造成了内存泄漏。

  • 资源对象未关闭

    比较典型的如 CursorFileStreamContentProvider 等,资源型对象往往都用了一些缓冲,在不使用时,应该及时关闭

  • 注册对象未注销

    常见的有 EventBus,广播等,一般都要在 onDestory() 中取消注册

  • 容器没有及时清理

    集合等容器类有可能被声明为静态,或者存储着静态数据;一般来讲容器占用内存也比较大,应该及时清理

  • Context 泄漏

    常见于将 Activity 级别的 Context 错误地传递到耗时任务中,导致因生命周期不一致导致的内存泄漏出现

  • WebView

    org.chromium.android_webview.AwContents 类中注册了 component callbacks,但是未正常反注册

内存泄漏的补救措施

很简单,内存泄漏的病根在于生命周期长度的不一致,对症下药即可。

  • 尽量避免使用静态成员变量

  • 不要在匿名内部类中进行耗时操作

  • 将非静态内部类转为静态内部类,如果需要外部引用,考虑使用弱引用

    Handler 内存泄漏的处理方案

  • 在 Activity 的 onDestory 回调中做好收尾工作

    • 移除 Handler 的消息
  • 静态变量置为空,取消注册,取消异步任务

    • 及时关闭资源对象
  • 及时清理容器,将集合里的东西clear,然后置为null

  • 在进行耗时操作时,使用 applicationContext 而不是 Activity 的 Context

  • WebView

    1. 在代码中使用 new 关键字而不是在布局文件中直接声明 WebView 节点

    2. 手动删除引用

      public void setConfigCallback(WindowManager windowManager) {
          try {
              Field field = WebView.class.getDeclaredField("mWebViewCore");
              field = field.getType().getDeclaredField("mBrowserFrame");
              field = field.getType().getDeclaredField("sConfigCallback");
              field.setAccessible(true);
              Object configCallback = field.get(null);
      
              if (null == configCallback) {
                  return;
              }
      
              field = field.getType().getDeclaredField("mWindowManager");
              field.setAccessible(true);
              field.set(configCallback, windowManager);
          } catch(Exception e) {
          }
      }
      

      然后在 Activity 中调用:

      public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setConfigCallback(WindowManager)getApplicationContext()
          .getSystemService(Context.WINDOW_SERVICE));
      }
      
      public void onDestroy() {
        setConfigCallback(null);
        super.onDestroy();
      }
      
      1. 从根源上解决
      @Override
      protected void onDestroy() {
        if( mWebView!=null) {
          // org.chromium.android_webview.AwContents#onDetachedFromWindow() 
          // if (isDestroyed()) return;
          ViewParent parent = mWebView.getParent();
          if (parent != null) {
            ((ViewGroup) parent).removeView(mWebView);
          }
      
          mWebView.stopLoading();
          mWebView.getSettings().setJavaScriptEnabled(false);
          mWebView.clearHistory();
          mWebView.clearView();
          mWebView.removeAllViews();
          mWebView.destroy();
        }
        // 在 onDestroy 之前先从父布局移除掉 WebView,否则无效
        super.onDestroy();
      }
      
  • 优化数据结构

    1. 优先使用ArrayMap 和基本类型,而非 HashMap 和包装类;
    2. 枚举在 Android 中占用内存较大,应该尽量避免使用;
    3. 学习使用 LruCache 和 SparseArray 等类
    4. 使用 RGB_8888 代替 RGB_565

相关文章

  • 说说 内存泄漏

    内存泄漏和内存溢出是两个概念。内存泄漏,指的是程序使用过的内存“忘记”归还给系统,造成长时间无谓地占用。内存溢出,...

  • 说说内存泄漏?

    一般什么情况下会导致内存泄漏问题? 基本知识储备 内存泄漏程序不再使用对象 A,但是因为 A 持有另外一个生命周期...

  • 说说Java内存泄漏

    Java中的内存管理 要了解Java中的内存泄漏,首先就得知道Java中的内存是如何管理的。 在Java程序中,我...

  • 【Android测试】内存泄漏检测 LeakCanary

    什么是内存泄漏和内存溢出?内存泄漏有什么危害?LeakCanary检测内存泄漏? 内存泄漏(Memory Leak...

  • 为何每次用完ThreadLocal都要调用remove()?

    什么是内存泄漏 Key 的泄漏 Value 的泄漏 如何避免内存泄露 什么是内存泄漏 内存泄漏指的是,当某一个对象...

  • Android如何打造高质量的应用?( 三)

    内存泄漏内存泄漏简单来说就是没有回收不再使用的内存,排查和解决内存泄漏也是内存优化无法避开的工作之一。很多内存泄漏...

  • Android内存泄漏场景及解决方法

    本文包括以下内容: 内存泄漏原理 Android内存泄漏发生的情况 检测内存泄漏的工具、方法 如何避免内存泄漏 更...

  • 内存泄漏

    什么是内存泄漏引起内存泄漏的原因野指针,空指针,僵尸对象 1.什么是内存泄漏 内存泄漏(Memory Leak)是...

  • 性能优化——内存泄漏(3)代码分析篇

    内存泄漏系列文章:性能优化——内存泄漏(1)入门篇性能优化——内存泄漏(2)工具分析篇性能优化——内存泄漏(3)代...

  • 性能优化——内存泄漏(2)工具分析篇

    内存泄漏系列文章:性能优化——内存泄漏(1)入门篇性能优化——内存泄漏(2)工具分析篇性能优化——内存泄漏(3)代...

网友评论

    本文标题:说说内存泄漏?

    本文链接:https://www.haomeiwen.com/subject/nnjmictx.html