精华内容
下载资源
问答
  • 最近刚安装Android studio2.2 版本,创建工程时老是报错 然后上网百度一下,发现是堆栈虚拟内存不足,解决办法是:在gradle.properties文件中加入如下代码:  MaxHeapSize=512m 然后,重新同步一下gradle就行了

    最近刚安装Android studio2.2 版本,创建工程时老是报错这里写图片描述

    然后上网百度一下,发现是堆栈虚拟内存不足,解决办法是:在gradle.properties文件中加入如下代码: 

    MaxHeapSize=512m
    然后,重新同步一下gradle就行了
     

    展开全文
  • 这俩个文件夹是在安装Android Studio的时候默认再c盘创建的,就算你创建的时候选择了其他盘,也会在c盘创建,尤其是你用Android Studio的时候需要创建一个虚拟的安卓手机,这个时候一个安卓手机avd文件就

    由于第一次进行Android开发,避免不了用到Google推出的ide->Android Studio,虽然idea也能进行安卓开发,但是idea中的配置总会报一些Google API的问题。
    在“C:/用户/username”目录下发现了.android和.gradle两个文件夹。这俩个文件夹是在安装Android Studio的时候默认再c盘创建的,就算你创建的时候选择了其他盘,也会在c盘创建,尤其是你用Android Studio的时候需要创建一个虚拟的安卓手机,这个时候一个安卓手机avd文件就9G了。

    步骤一

    • 把.android/avd/目录下的模拟器“xxx.avd”文件移动到D盘对应位置。
    • 修改.android/avd/下的配置文件“xxx.ini”中的路径地址。
    • 打开Android Studio试一下模拟器avd是否能正常启动和使用。

    步骤二

    • 把.gradle和.AndroidStudio移动到D盘对应位置。
    • 然后找到Android Studio安装目录下的\bin\idea.properties文件,打开并查找“idea.config.path=”和“idea.system.path=”,把“=”号右边的${user.home}改为你想放到的位置,并把前面的“#”去掉。
    • 在idea.properties文件最底部加上Gradle的路径配置:gradle.user.home=你想放的文件夹路径/.gradle

    然后重启一下Android Studio

    展开全文
  • 其中在Android虚拟机中采用的是根节点搜索算法枚举根节点判断是否是垃圾,虚拟机会从GC Roots开始遍历,如果一个节点找不到一条到达GC Roots的路线,也就是没和GC Roots 相连,那么就证明该引用无效,可以被回收,...
  • [img=https://img-bbs.csdn.net/upload/201911/05/1572940312_232553.png][/img][img=https://img-bbs.csdn.net/upload/201911/05/1572940312_568124.png][/img] 哪里出了问题????? 求指教
  • 其中在Android虚拟机中采用的是根节点搜索算法枚举根节点判断是否是垃圾,虚拟机会从GC Roots开始遍历,如果一个节点找不到一条到达GC Roots的路线,也就是没和GC Roots 相连,那么就证明该引用无效,可以被回收,内

    1.内存泄漏是什么

    内存泄漏就是一些已经不使用的对象还存在于内存之中且垃圾回收机制无法回收它们,导致它们常驻内存,会使内存消耗越来越大,最终导致程序性能变差。
    其中在Android虚拟机中采用的是根节点搜索算法枚举根节点判断是否是垃圾,虚拟机会从GC Roots开始遍历,如果一个节点找不到一条到达GC Roots的路线,也就是没和GC Roots 相连,那么就证明该引用无效,可以被回收,内存泄漏就是存在一些不好的调用导致一些无用对象和GC Roots相连,无法被回收。既然知道了什么是内存泄漏,自然就知道如何去避免了,就是我们在写代码的时候尽量注意产生对无用对象长时间的引用

    2.案例分析

    内存泄漏的示例代码如下:

    // 导致内存泄漏的代码
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_test);
    textView = (TextView) findViewById(R.id.text);
    final Handler handler = new Handler();
    handler.post(new Runnable() {
     @Override
     public void run() {
       textView.setText(String.valueOf(timer++));
       handler.postDelayed(this, 1000);
      }
     });
    }
    2.1内存分析工具

    Android的内存泄漏分析工具常用有Android Studio和基于eclipse的MAT(Memory Analyzer Tool)。通过两者配合,可以发挥出奇妙的效果。Android Studio能够快速定位内存泄漏的Activity,MAT能根据已知的Activity快速找出内存泄漏的根源。

    1.第一步:强制GC,生成Java Heap文件

    我们都知道Java有一个非常强大的垃圾回收机制,会帮我回收无引用的对象,这些无引用的对象不在我们内存泄漏分析的范畴,Android Studio有一个Android Monitors帮助我们进行强制GC,获取Java Heap文件。

    强制GC:点击Initate GC(1)按钮,建议点击后等待几秒后再次点击,尝试多次,让GC更加充分。然后点击Dump Java Heap(2)按钮,然后等到一段时间,生成有点慢。



    生成的Java Heap文件会在新建窗口打开。



    2.分析内存泄漏的Activity

    点击Analyzer TasksPerform Analysis(1)按钮,然后等待几秒十几秒不等,即可找出内存泄漏的Activity(2)。


    那么我们就可以知道内存泄漏的Activity,因为这个例子比较简单,其实在(3)就已经可以看到问题所在,如果比较复杂的问题Android Studio并不够直观,不够MAT方便,如果Android Studio无法解决我们的问题,就建议使用MAT来分析,所以下一步我们就生成标准的hprof文件,通过MAT来找出泄漏的根源。

    3.转换成标准的hprof文件

    刚才生成的Heap文件不是标准的Java Heap,所以MAT无法打开,我们需要转换成标准的Java Heap文件,这个工具Android Studio就有提供,叫做Captures,右击选中的hprofExport to standard .hprof选择保存的位置,即可生成一个标准的hprof文件。



    4.MAT打开hprof文件

    MAT的下载地址,使用方式和eclipse一样,这里就不多说了,打开刚才生成的hprof文件。点击(1)按钮打开Histogram。(2)这里是支持正则表达式,我们直接输入Activity名称,点击enter键即可。


    搜索到了目标的Activity


    右击搜索出来的类名,选择Merge Shortest Paths to GC Rootsexclude all phantom/weak/soft etc. references,来到这一步,就可以看到内存泄漏的原因,我们就需要根据内存泄漏的信息集合我们的代码去分析原因。



    6.根据内存泄漏信息和代码分析原因

    使用Handler案例分析,给出的信息是Thread和android.os.Message,这个Thread和Message配合通常是在Handler使用,结合代码,所以我猜测是Handler导致内存泄漏问题,查看代码,直接就在函数中定义了一个final的Handler用来定时任务,在Activity的onDestroy后,这个Handler还在不断地工作,导致Activity无法正常回收。

    修改代码如下:

    @Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_test);
    textView = (TextView) findViewById(R.id.text);
    handler.post(new Runnable() {
     @Override
     public void run() {
      textView.setText(String.valueOf(timer++));
      if (handler != null) {
       handler.postDelayed(this, 1000);
      }
     }
    });
    }
    private Handler handler = new Handler();
    @Override
    protected void onDestroy() {
     super.onDestroy();
     // 避免Handler导致内存泄漏
     handler.removeCallbacksAndMessages(null);
     handler = null;
    }

    3.常见的内存泄漏分析

    内存泄漏的主要问题可以分为以下几种类型:

        a.静态变量引起的内存泄漏
        b.非静态内部类引起的内存泄漏
        c.资源未关闭引起的内存泄漏

    3.1静态变量引起的内存泄漏

    在java中静态变量的生命周期是在类加载时开始,类卸载时结束。换句话说,在android中其生命周期是在进程启动时开始,进程死亡时结束。所以在程序的运行期间,如果进程没有被杀死,静态变量就会一直存在,不会被回收掉。如果静态变量强引用了某个Activity中变量,那么这个Activity就同样也不会被释放,即便是该Activity执行了onDestroy(不要将执行onDestroy和被回收划等号)。这类问题的解决方案为:1.寻找与该静态变量生命周期差不多的替代对象。2.若找不到,将强引用方式改成弱引用。比较典型的例子如下:

    单例引起的Context内存泄漏:

    public class IMManager {
      private Context context;
      private static IMManager mInstance;
     
      public static IMManager getInstance(Context context) {
        if (mInstance == null) {
          synchronized (IMManager.class) {
            if (mInstance == null)
              mInstance = new IMManager(context);
          }
        }
        return mInstance;
      }
     
      private IMManager(Context context) {
        this.context = context;
      }
     
    }

    当调用getInstance时,如果传入的context是Activity的context。只要这个单例没有被释放,这个Activity也不会被释放。

    解决方案:传入Application的context,因为Application的context的生命周期比Activity长,可以理解为Application的context与单例的生命周期一样长,传入它是最合适的。修改如下:

    public class IMManager {
      private Context context;
      private static IMManager mInstance;
     
      public static IMManager getInstance(Context context) {
        if (mInstance == null) {
          synchronized (IMManager.class) {
            if (mInstance == null)
              //将传入的context转换成Application的context
              mInstance = new IMManager(context.getApplicationContext());
          }
        }
        return mInstance;
      }
     
      private IMManager(Context context) {
        this.context = context;
      }
     
    }

    3.2非静态内部类引起的内存泄漏

    在java中,创建一个非静态的内部类实例,就会引用它的外围实例。如果这个非静态内部类实例做了一些耗时的操作,就会造成外围对象不会被回收,从而导致内存泄漏。这类问题的解决方案为:1.将内部类变成静态内部类 2.如果有强引用Activity中的属性,则将该属性的引用方式改为弱引用。3.在业务允许的情况下,当Activity执行onDestory时,结束这些耗时任务。

    1.内部线程造成的内存泄漏:

    public class LeakAty extends Activity {
     
      @Override
      protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.aty_leak);
        test();
      }
     
      public void test() {
        //匿名内部类会引用其外围实例LeakAty.this,所以会导致内存泄漏
        new Thread(new Runnable() {
     
          @Override
          public void run() {
            while (true) {
              try {
                Thread.sleep(1000);
              } catch (InterruptedException e) {
                e.printStackTrace();
              }
            }
          }
        }).start();
      }
      }

    解决方案:将非静态匿名内部类修改为静态匿名内部类

    public class LeakAty extends Activity {
     
      @Override
      protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.aty_leak);
        test();
      }
      //加上static,变成静态匿名内部类
      public static void test() {
        new Thread(new Runnable() {
     
          @Override
          public void run() {
            while (true) {
              try {
                Thread.sleep(1000);
              } catch (InterruptedException e) {
                e.printStackTrace();
              }
            }
          }
        }).start();
      }
    }

    另外一个例子:

        package com.example.memoryleak;  
          
        import java.util.ArrayList;  
        import java.util.List;  
          
        import android.app.Activity;  
        import android.os.Bundle;  
          
        public class LeakActivity extends Activity {  
            private List<String> list = new ArrayList<String>();  
              
          
            @Override  
            protected void onCreate(Bundle savedInstanceState) {  
                super.onCreate(savedInstanceState);  
                  
                //模拟Activity一些其他的对象  
                for(int i=0; i<10000;i++){  
                    list.add("Memory Leak!");  
                }  
                  
                //开启线程  
                new MyThread().start();  
                  
            }  
              
              
            public class MyThread extends Thread{  
          
                @Override  
                public void run() {  
                    super.run();  
                      
                    //模拟耗时操作  
                    try {  
                        Thread.sleep(10 * 60 * 1000);  
                    } catch (InterruptedException e) {  
                        e.printStackTrace();  
                    }  
                      
                }  
                  
                  
            }  
        }  
    我们知道上面的例子代码中我们知道内部类会持有外部类的引用,如果内部类的生命周期过长,会导致外部类内存泄露,那么你会问,我们应该怎么写那不会出现内存泄露的问题呢?既然内部类不行,我们就外部类或者static的内部类,如果我们需要用到外部类里面的一些东西,我们可以将外部类Weak Reference传递进去

    修改如下:

        package com.example.memoryleak;  
          
        import java.lang.ref.WeakReference;  
        import java.util.ArrayList;  
        import java.util.List;  
          
        import android.app.Activity;  
        import android.os.Bundle;  
          
        public class LeakActivity extends Activity {  
            private List<String> list = new ArrayList<String>();  
              
          
            @Override  
            protected void onCreate(Bundle savedInstanceState) {  
                super.onCreate(savedInstanceState);  
                  
                //模拟Activity一些其他的对象  
                for(int i=0; i<10000;i++){  
                    list.add("Memory Leak!");  
                }  
                  
                //开启线程  
                new MyThread(this).start();  
                  
            }  
              
              
            public static class MyThread extends Thread{  
                private WeakReference<LeakActivity> mLeakActivityRef;  
                  
                public MyThread(LeakActivity activity){  
                    mLeakActivityRef = new WeakReference<LeakActivity>(activity);  
                }  
          
                @Override  
                public void run() {  
                    super.run();  
                      
                    //模拟耗时操作  
                    try {  
                        Thread.sleep(10 * 60 * 1000);  
                    } catch (InterruptedException e) {  
                        e.printStackTrace();  
                    }  
                      
                    //如果需要使用LeakActivity,我们需要添加一个判断  
                    LeakActivity activity = mLeakActivityRef.get();  
                    if(activity != null){  
                        //do something  
                    }  
                      
                }  
                  
                  
            }  
        }  

    2.Handler造成的内存泄漏

    泄漏代码如下:

        package com.example.memoryleak;  
          
        import android.app.Activity;  
        import android.os.Bundle;  
        import android.os.Handler;  
        import android.os.Message;  
          
        public class LeakActivity extends Activity {  
          
            @Override  
            protected void onCreate(Bundle savedInstanceState) {  
                super.onCreate(savedInstanceState);  
                  
                MyHandler handler = new MyHandler();  
                handler.sendMessageDelayed(Message.obtain(), 10 * 60 * 1000);  
            }  
              
              
            public class MyHandler extends Handler{  
          
                @Override  
                public void handleMessage(Message msg) {  
                    super.handleMessage(msg);  
                }  
            }  
                  
        }  

    我们知道使用MyHandler发送消息的时候,Message会被加入到主线程的MessageQueue里面,而每条Message的target会持有MyHandler对象,而MyHandler的this$0又会持有LeakActivity对象, 所以我们在旋转屏幕的时候,由于每条Message被延迟了 10分钟,所以必然会导致LeakActivity泄露,所以我们需要将代码进行修改下:

        package com.example.memoryleak;  
          
        import java.lang.ref.WeakReference;  
          
        import android.app.Activity;  
        import android.os.Bundle;  
        import android.os.Handler;  
        import android.os.Message;  
          
        public class LeakActivity extends Activity {  
            MyHandler handler;  
          
            @Override  
            protected void onCreate(Bundle savedInstanceState) {  
                super.onCreate(savedInstanceState);  
                  
                handler = new MyHandler(this);  
                handler.sendMessageDelayed(Message.obtain(), 10 * 60 * 1000);  
            }  
              
              
            public static class MyHandler extends Handler{  
                public WeakReference<LeakActivity> mLeakActivityRef;  
                  
                public MyHandler(LeakActivity leakActivity) {  
                    mLeakActivityRef = new WeakReference<LeakActivity>(leakActivity);  
                }  
          
                @Override  
                public void handleMessage(Message msg) {  
                    super.handleMessage(msg);  
                      
                    if(mLeakActivityRef.get() != null){  
                        //do something  
                    }  
                }  
            }  
          
          
            @Override  
            protected void onDestroy() {  
                handler.removeCallbacksAndMessages(null);  
                super.onDestroy();  
            }  
                  
        }  

    上面的代码就能保证LeakActivity不会被泄露,注意我们在Activity的onDestory方法中使用了handler.removeCallbacksAndMessages(null),这样子能保证LeakActivity退出的时候,每条Message的target  MyHandler也会被释放, 所以我们在使用非static的内部类的时候,要注意该内部类的生命周期是否比外部类要长,如果是的话我们可以使用上面的解决方法。


    3.3资源未关闭引起的泄漏

    1.资源对象没有关闭,比如数据库操作中得Cursor,IO操作的对象

    2.调用了registerReceiver注册广播后未调用unregisterReceiver()来取消

    3.调用了View.getViewTreeObserver().addOnXXXListener ,而没有调用View.getViewTreeObserver().removeXXXListener

    4.Android 3.0以前,没有对不在使用的Bitmap调用recycle(),当然在Android 3.0以后就不需要了




    展开全文
  • 对于内存泄漏,在Android中如果不注意的话,还是很容易出现的,尤其是在Activity中,比较容易出现,下面我就说下自己是如何...其中在Android虚拟机中采用的是根节点搜索算法枚举根节点判断是否是垃圾,虚拟机会从G...

    对于内存泄漏,在Android中如果不注意的话,还是很容易出现的,尤其是在Activity中,比较容易出现,下面我就说下自己是如何查找内存泄露的。

    首先什么是内存泄漏?

    内存泄漏就是一些已经不使用的对象还存在于内存之中且垃圾回收机制无法回收它们,导致它们常驻内存,会使内存消耗越来越大,最终导致程序性能变差。
    其中在Android虚拟机中采用的是根节点搜索算法枚举根节点判断是否是垃圾,虚拟机会从GC Roots开始遍历,如果一个节点找不到一条到达GC Roots的路线,也就是没和GC Roots 相连,那么就证明该引用无效,可以被回收,内存泄漏就是存在一些不好的调用导致一些无用对象和GC Roots相连,无法被回收。

    既然知道了什么是内存泄漏,自然就知道如何去避免了,就是我们在写代码的时候尽量注意产生对无用对象长时间的引用,说起来简单,但是需要足够的经验才能达到,所以内存泄漏还是比较容易出现的,既然不容易完全避免,那么我们就要能发现程序中出现的内存泄漏并修复它,
    下面我就说说如何发现内存泄漏的吧。

    查找内存泄漏:

    比如说下面这个代码:

    public class MainActivity extends AppCompatActivity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            String string = new String();
    
        }
    
        public void click(View view){
            Intent intent = new Intent();
            intent.setClass(getApplicationContext(),SecondActivity.class);
            startActivity(intent);
        }
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    public class SecondActivity extends AppCompatActivity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_second);
            Runnable runnable = new Runnable() {
                @Override
                public void run() {
                    try {
                        Thread.sleep(8000000L);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            };
            new Thread(runnable).start();
        }
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    每次跳转到这个Activity中时都会调用一个线程,然后这个线程会执行runnable的run方法 由于Runnable是一个匿名内部对象 所以握有SecondActivity的引用,因此
    很简单的两个Activity,可由MainActivity跳转到SecondActivity中,
    下面我们从MainActivity跳到SecondActivity 然后从SecondActivity返回MainActivity,连续这样5次 ,最终返回MainActivity,按照常理来说,我们从SecondActivity返回MainActivity之后 SecondActivity就该被销毁回收,可实际可能并不是这样。

    这时候要判断发没发生内存溢出就要使用工具了!下面有两种方式

    1.利用MAT工具查找

    首先打开AS中的Android Device Monitor工具 具体位置如下图:
    AS Android Device Monitor位置
    打开后会出现如下的界面
    ADM界面
    先选中你要检测的应用的包名,然后点击下图画圈的地方,会在程序包名后标记一个图标

    接下来要做的就是操作我们的app 来回跳转5次。
    之后点击下图的图标 就可导出hprof文件进行分析了

    导出文件如下图所示:
    hprof文件
    得到了hprof文件 我们就可以利用MAT工具进行分析了,
    打开MAT工具
    如果没有 可以在下面网址下载
    MAT工具下载地址

    界面如下图所示:

    打开我们先前导出的hprof文件 ,不出意外会报下面的错误

    这是因为MAT是用来分析java程序的hprof文件的 与Android导出的hprof有一定的格式区别,因此我们需要把导出的hprof文件转换一下,sdk中提供给我们转换的工具 hprof-conv.exe 在下图的位置
    hprof-conv位置
    接下来我们cd到这个路径下执行这个命令转换我们的hprof文件即可,如下图
    转换hprof文件
    其中 hprof-conv 命令 这样使用
    hprof-conv 源文件 输出文件
    比如 hprof-conv E:\aaa.hprof E:\output.hprof
    就是 把aaa.hprof 转换为output.hprof输出 output.hprof就是我们转换之后的文件,图中 mat2.hprof就是我们转换完的文件。

    接下来 我们用MAT工具打开转换之后的mat2.hprof文件即可 ,打开后不报错 如下图所示:
    MAT打开hprof文件
    之后我们就可以查看当前内存中存在的对象了,由于我们内存泄漏一般发生在Activity中,因此只需要查找Activity即可。
    点击下图中标记的QQL图标 输入 select * from instanceof android.app.Activity
    类似于 SQL语句 查找 Activity相关的信息 点击 红色叹号执行后 如下图所示:
    QQL

    接下来 我们就可以看到下面过滤到的Activity信息了
    如上图所示, 其中内存中还存在 6个SecondActivity实例,但是我们是想要全部退出的,这表明出现了内存泄漏

    其中 有 Shallow size 和 Retained Size两个属性

    Shallow Size
    对象自身占用的内存大小,不包括它引用的对象。针对非数组类型的对象,它的大小就是对象与它所有的成员变量大小的总和。
    当然这里面还会包括一些java语言特性的数据存储单元。针对数组类型的对象,它的大小是数组元素对象的大小总和。
    Retained Size
    Retained Size=当前对象大小+当前对象可直接或间接引用到的对象的大小总和。(间接引用的含义:A->B->C, C就是间接引用)
    不过,释放的时候还要排除被GC Roots直接或间接引用的对象。他们暂时不会被被当做Garbage。
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    接下来 右击一个SecondActivity

    选择 with all references
    打开如下图所示的页面

    查看下图的页面
    看到 this0Activitythis0引用了这个Activity而this0是表示 内部类的意思,也就是一个内部类引用了Activity 而 this$0又被 target引用 target是一个线程,原因找到了,内存泄漏的原因 就是 Activity被 内部类引用 而内部类又被线程使用 因此无法释放,我们转到这个类的代码处查看

    public class SecondActivity extends AppCompatActivity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_second);
            Runnable runnable = new Runnable() {
                @Override
                public void run() {
                    try {
                        Thread.sleep(8000000L);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            };
            new Thread(runnable).start();
        }
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    确实 在 SecondActivity中 存在Runnable 内部类对象,然后又被线程 使用,而线程要执行8000秒 因此 SecondActivity对象被引用 无法释放,导致了内存溢出。
    要解决这种的内存溢出,要及时在Activity退出时结束线程(不过不大好结束。。),或者良好的控制线程执行的时间即可。

    这样我们就找出了这个程序中的内存溢出。

    2.直接利用Android Studio的 Monitor Memory 查找内存溢出
    还是利用上面那个程序,我就简单点说了。

    首先 在手机上运行程序,打开AS的 Minotor 界面 查看Memory 图像

    点击 小卡车图标(图中1位置图标) 可以触发一次 GC

    点击 图中2位置图标可以查看hprof文件

    左边是 内存中的对象,在里面找 Activity 看存不存在我们希望已经回收的Activity 如果 出现我们期望已经回收的Activity,单击 就会在右边显示它的总的个数,点击右边的某个,可以显示 它的GC Roots的树关系图 ,查看关系图就可以找出发生内存泄漏的位置(类似于第一种方式)

    这样就完成了内存泄漏的查找。

    其中内存泄漏产生的原因在Android中大致分为以下几种:

    1.static变量引起的内存泄漏
    因为static变量的生命周期是在类加载时开始 类卸载时结束,也就是说static变量是在程序进程死亡时才释放,如果在static变量中 引用了Activity 那么 这个Activity由于被引用,便会随static变量的生命周期一样,一直无法被释放,造成内存泄漏。

    解决办法:
    在Activity被静态变量引用时,使用 getApplicationContext 因为Application生命周期从程序开始到结束,和static变量的一样。

    2.线程造成的内存泄漏
    类似于上述例子中的情况,线程执行时间很长,及时Activity跳出还会执行,因为线程或者Runnable是Acticvity内部类,因此握有Activity的实例(因为创建内部类必须依靠外部类),因此造成Activity无法释放。
    AsyncTask 有线程池,问题更严重

    解决办法:
    1.合理安排线程执行的时间,控制线程在Activity结束前结束。
    2.将内部类改为静态内部类,并使用弱引用WeakReference来保存Activity实例 因为弱引用 只要GC发现了 就会回收它 ,因此可尽快回收

    3.BitMap占用过多内存
    bitmap的解析需要占用内存,但是内存只提供8M的空间给BitMap,如果图片过多,并且没有及时 recycle bitmap 那么就会造成内存溢出。

    解决办法:
    及时recycle 压缩图片之后加载图片

    4.资源未被及时关闭造成的内存泄漏
    比如一些Cursor 没有及时close 会保存有Activity的引用,导致内存泄漏

    解决办法:
    在onDestory方法中及时 close即可

    5.Handler的使用造成的内存泄漏
    由于在Handler的使用中,handler会发送message对象到 MessageQueue中 然后 Looper会轮询MessageQueue 然后取出Message执行,但是如果一个Message长时间没被取出执行,那么由于 Message中有 Handler的引用,而 Handler 一般来说也是内部类对象,Message引用 Handler ,Handler引用 Activity 这样 使得 Activity无法回收。

    解决办法:
    依旧使用 静态内部类+弱引用的方式 可解决

    其中还有一些关于 集合对象没移除,注册的对象没反注册,代码压力的问题也可能产生内存泄漏,但是使用上述的几种解决办法一般都是可以解决的。

    参考资料:
    使用Android studio分析内存泄露

    Android内存泄漏分析及调试

    java对象的强引用,软引用,弱引用和虚引用

    Android内存泄漏终极解决篇(下)

    				<script>
    					(function(){
    						function setArticleH(btnReadmore,posi){
    							var winH = $(window).height();
    							var articleBox = $("div.article_content");
    							var artH = articleBox.height();
    							if(artH > winH*posi){
    								articleBox.css({
    									'height':winH*posi+'px',
    									'overflow':'hidden'
    								})
    								btnReadmore.click(function(){
    									articleBox.removeAttr("style");
    									$(this).parent().remove();
    								})
    							}else{
    								btnReadmore.parent().remove();
    							}
    						}
    						var btnReadmore = $("#btn-readmore");
    						if(btnReadmore.length>0){
    							if(currentUserName){
    								setArticleH(btnReadmore,3);
    							}else{
    								setArticleH(btnReadmore,1.2);
    							}
    						}
    					})()
    				</script>
    				</article>
    
    展开全文
  • android studio是第一次使用,很多使用细则不太了解,今天先写虚拟手机与真机的设置,以后再陆续补充 虚拟手机设置 Tools ->android->AVD manager,设置一些相关参数即可,切记不要使用太新的手机型号因为这些手机...
  • Android开发(1)Android Studio平台问题综合 本学期的软件工程课设小组决定做一个安卓平台的触控笔记软件开发。所采用的的IDE为Android Studio,选用语言为java和kotlin。本篇博客为长期更新型博客,会有时间戳进行...
  • 对于电脑运行内存小于8G的,在Android studio虚拟设备上运行APP会十分吃力,那就不得不使用真机来进行调试。 1.首先点击菜单栏tools->SDK Manager->Android SDK->SDK Tools,勾选Google USB Driver,点击...
  • **前言:**对于使用AMD处理器的同学,Android Studio真的很不友好,不支持inter 虚拟架构,配置了一天真的太伤了,所以写一篇博客帮助大家避雷。 笔记本的系统环境: 1、win10 64位家庭版; 2、8G内存。 一、安装...
  • Android studio 2.2 当中有一项新的功能:Dex In Process. 这项功能可以动态的...你只需要修改 gradle.properties 这个文件,增加虚拟内存分配给 gradle 从1GB 到 最小 2GB。 org.gradle.jvmargs=-Xmx1536m  Andro
  • 根据如上的提示,谷歌翻译之后说是Gradle虚拟内存不足。然后我就将之前的Gradle目录更换到另一个磁盘,红色圈圈是修改过的。 点击OK保存,重新启动as好了,又可以愉快的敲代码了。 第二天又高高兴兴的来上班,想...
  • Android SDK (Software Development Kit) 软件开发工具包,包含了各种插件以及工具当Studio安装完成后打开File--&...对于4G内存的电脑,当安装Studio的时候可以不安装虚拟设备,直接用手机调试。...
  • 听网易云的时候死机的,都在敲安卓代码,虚拟机有时候开有时候没开,但是CPU虚拟化是开了的 还有个问题是我前几天加了内存,拿了个金斯顿的DDR4 2134的和我原来的三星DDR4 2133的组成8G双通道,平时倒是没啥问题,一...
  • VirtualApp(以下简称:VA)是一款运行于Android系统的沙盒产品,可以理解为轻量级的“Android虚拟机”。其产品形态为高可扩展,可定制的集成SDK,您可以基于VA或者使用VA定制开发各种看似不可能完成的项目。VA目前被...
  • 说你剩余内存不够java跑虚拟机所被分配到的虚拟内存。(本电脑为8g内存,此时剩余1g多一点)这时候有2种解决方案: 切换jdk为AndroidStudio自带jdk 选择菜单中的project structure 选择AndroidStudio自带的jdk,...
  • android 学习(1)

    2015-07-07 22:20:00
    androidstudio安装注意点 1JDK安装需配置环境变量 2安装遇到haxm错误需要进入BIOS打开CPU的VT(虚拟内存) 4跑仿真器时,hax问题出在安装时的内存分配太小,建议越大越好。 5离线安装,连不上外网,则进入init的...
  • 刚开机IDEA状态内存就占用达到80%,打开AndroidStudio直接飙到90%,严重影响工作。但查看任务管理器,并没有发现是什么东西在占用内存。 收集了网上N多方案,什么关闭不必要的服务,关闭Update之类,禁用superfetch...
  • 原文:Android零基础入门第14节:使用高速Genymotion,跨入火箭时代无论是使用Eclipse,还是Android Studio,使用自带的Android模拟器,不仅很费电脑内存,模拟器开机和运行程序的速度很慢,严重影响开发效率。...
  • ==>在AndroidStudio3.0以下版本支持Lambda ==>小说阅读页面的切换动画及整体架构都来自这个项目。 ==>标签效果 应用展示 更新记录 更新2020-03-15 更新三方库 Android 8.0禁止使用DownloadServic
  • 而且使用本方法的时候,Android Studio 会有预览效果,如下图: 不过不用担心,只是预览效果,运行的时候只有下拉才会出现~ 3.方法三 Java代码设置 final RefreshLayout refreshLayout = (RefreshLayout) ...
  • 如果你的 android studio 版本低于3.4.2版,有可能会打不开我的Demo,只需要修改Demo里面 build.gradle(project) 文件中的: dependencies { classpath 'com.android.tools.build:gradle:3.4.2' //把3.4.2改成...
  • java开发问题收集

    2017-07-11 09:54:04
    原因:mac的虚拟内存一般是内存空间不够用才会开启,用来做内存交换。 解决方案:让内存飙升,开启一些应用什么的,像我以前开发安卓,直接开启内存消耗比较大的android studio,再安装的时候就没问题了。 maven...
  • ADB常用命令记录

    2018-09-18 10:01:02
    2018.10.12:(Android Studio) adb shell:进入Android底层Linux系统 ps:查看系统里面所有进程 USER 哪个用户运行的 PID 进程ID PPID 进程的父进程ID VSIZE 虚拟的尺寸 RSS 常驻内存的代销 查看系统...
  • 电脑上内存不足时打开Android Studio 总会看到如下报错,也就是你的电脑内存不够跑一个虚拟机了,也说明虚拟机非常耗内存。今天来学习一下~虚拟机的概念:虚拟机(Virtual Machine)指通过软件模拟的具有完整硬件...
  • 什么是HAXM呢?它是Intel Hardware Accelerated Execution Manager (Intel® HAXM) 缩写,是Intel为了在开发主机上... 在[1]中Android Studio安装过程中, HAXM缺省设置占用的内存为512MB。根据[4], 由于Nexus 5
  • 安卓与ROS通信开发——1、软件开放环境配置 开发环境配置 以下为开发环境配置: ...2)swap:中文是"交换空间",充当ubuntu的虚拟内存,一般的大小为电脑物理内存的2倍左右,逻辑分区,空间起始位置,用于"swa

空空如也

空空如也

1 2
收藏数 35
精华内容 14
关键字:

androidstudio虚拟内存