精华内容
下载资源
问答
  • 内存抖动

    2021-01-06 11:08:21
    <div><p>内存抖动,不知道你发现没有...ShadowImageView dispatchDraw()死循环</p><p>该提问来源于开源项目:yingLanNull/ShadowImageView</p></div>
  • 一、 垃圾回收算法总结、 二、 分代收集算法补充、 三、 查看 Java 虚拟机、 四、 获取 Android 应用可...五、 内存抖动标志、 六、 排查内存抖动、 七、 常见的造成内存抖动操作、 八、 从内存优化角度选择集合





    一、 垃圾回收算法总结



    【Android 内存优化】垃圾回收算法 ( 内存优化总结 | 常见的内存泄漏场景 | GC 算法 | 标记清除算法 | 复制算法 | 标记压缩算法 ) 介绍了 标记清除算法 , 复制算法 , 标记压缩算法 , 三种垃圾回收算法 ;

    【Android 内存优化】垃圾回收算法 ( 分代收集算法 | Serial 收集器 | ParNew 收集器 | Parallel Scavenge 收集器 | CMS 并发标记清除收集器 ) 博客中介绍了分代收集算法 , 并对常用的垃圾收集器进行了介绍 , 下面总结一下垃圾回收算法 , 与垃圾收集器 ;



    1. 垃圾回收算法 :


    ① 标记清除算法 : 标记可回收的对象 , 之后将标记的对象回收 ; 内存碎片化 ;

    ② 复制算法 : 使用一半内存 , 当无法申请内存时 , 直接将有效对象拷贝到另一半内存中 ; 浪费内存 , 效率低下 ;

    ③ 标记压缩算法 : 标记回收内存对象 , 整理内存 ; 增加了开销 ;

    ④ 分代收集算法 : 将内存分为年轻代 , 老年代 , 持久代 , 三块区域 ; 不同生命周期的内存对象进行不同的管理 ;



    2. 垃圾收集器总结 :


    ① Serial 收集器 : 年轻代 , 复制算法 , 单线程 GC , 暂停用户线程 ;

    ② ParNew 收集器 : 年轻代 , 复制算法 , 多线程 GC , 暂停用户线程 ;

    ③ Parallel Scavenge 收集器 : 年轻代 , 复制算法 , 多线程 GC , 暂停用户线程 ( 关注吞吐量 ) ;

    ④ CMS ( Concurrent Mark Sweep ) 并发标记清除收集器 ( 重点 ) : 老年代 , 标记-清除算法 , 多线程 GC , 与用户线程并发 ( 短时间暂停 ) ;

    ⑤ Parallel Old 收集器 : 老年代 , 标记整理算法 , 多线程 GC , 暂停用户线程 ;

    ⑥ Serial Old 收集器 : 老年代 , 标记整理算法 , 单线程 GC , 暂停用户线程 ;





    二、 分代收集算法补充



    【Android 内存优化】垃圾回收算法 ( 分代收集算法 | Serial 收集器 | ParNew 收集器 | Parallel Scavenge 收集器 | CMS 并发标记清除收集器 ) 一、 分代收集算法 章节对分代收集算法做了下简介 , 感觉没有描述清楚 , 再补充下 :


    1. 主流垃圾回收算法 : JVM , DVM 都采用了 分代收集算法 , 将内存划分成不同的内存区域 , 不同的区域采用不同的垃圾收集算法 , 这是目前主流的 Java 虚拟机都在使用的垃圾回收算法 ;


    2. 分代收集算法的核心思想是 :

    • 不同的对象声明周期不同 , 承担的功能不同 ;
    • 有些对象声明周期比较长如 Android 中的 Application , Activity 等组件 ;
    • 有的对象生命周期很短 , 如打印日志时创建打印内容字符串 , 打印完毕后 , 该字符串对象马上就没用了 ;
    • 这里要将不同的生命周期长度的对象 , 分别使用不同的垃圾回收机制进行处理 , 这样可以提高垃圾收集的效率 ;

    3. 分治思想 : 垃圾对象收集时 , 需要对整个内存空间进行扫描 , 这样消耗很大 , 这里我们将内存分区 , 将生命周期短的对象放在一块内存中 , 生命周期长的对象放在另一块内存中 , 这样针对不同的内存块 , 采取不同的垃圾回收策略 ; ( 分治思想 )


    4. 内存块分块 : 将 Java 内存堆分为 年轻代 , 老年代 , 新创建的对象放在年轻代中 , 老对象转移到老年代中 ;


    5. 年轻代内存分区 : 年轻代内存分为 Eden 和 Survivor 两个区域 , Survivor 区域又分为 From Space 和 To Space ;

    复制算法分区 : 很明显 Eden 和 Survivor 是复制算法中的两个区域 , From Space 和 To Space 也是复制算法中的两个区域 ;


    6. 年轻代内存策略 : 复制算法 ;

    • 新对象存放 : 新创建的对象都放在年龄代内存中的 Eden 区域中 ;

    • 第一次复制算法 : 当 Eden 区域放满时 , 将存活的区域放到 Survivor 区域中的 From Space ( To Space ) 区域中 ;

    • 第二次复制算法 : 当 From Space ( To Space ) 区域中存放后 , 会将年龄不足晋升的对象复制到另一侧的 To Space ( From Space ) 区域中 ;

    • 晋升机制 : 年轻代内存中 , 一旦对象经理的 GC 次数达到一定阈值 , 就会晋升到老年代内存中 ;


    7. 老年代内存策略 : 标记整理算法 ; Android 中使用的是 CMS 垃圾收集器 ;





    三、 查看 Java 虚拟机



    查看 Java 虚拟机 : 在命令行中执行 java -version , 即可查看当前 java 虚拟机情况 ;

    C:\Users\octop>java -version
    java version "1.8.0_221"
    Java(TM) SE Runtime Environment (build 1.8.0_221-b11)
    Java HotSpot(TM) 64-Bit Server VM (build 25.221-b11, mixed mode)
    
    C:\Users\octop>
    

    在这里插入图片描述

    上述虚拟机是 HotSpot 虚拟机





    四、 获取 Android 应用可使用最大内存



    OOM 就是应用的内存超过了堆的最大值 , 内存分配的单位是进程 , 每个进程都会有一定的内存限制 ,


    1. 获取当前 Android 手机的最大使用用内存 :


    ① 代码获取 : 调用 ActivityManager 对象的 getMemoryClass 方法获得内存对象 ;

    ② 执行如下命令 :

    adb shell getprop dalvik.vm.heapsize
    

    命令执行结果 :

    C:\Users\octop>adb shell getprop dalvik.vm.heapsize
    512m
    
    C:\Users\octop>
    

    在这里插入图片描述


    2. 获取其它值 :

    # 获取 app 最大申请内存, 超过就 OOM 
    $ adb shell getprop dalvik.vm.heapsize
    512m
    
    # 获取初始内存大小
    $ adb shell getprop dalvik.vm.heapstartsize
    8m
    
    # 正常情况下的内存值
    $ adb shell getprop dalvik.vm.heapgrowthlimit
    192m
    

    3 . 指定极限大小 :AndroidManifest.xml 中的 application 标签中指定 android:largeHeap 为 true , 为该进程设置堆内存极限大小 ;





    五、 内存抖动标志



    在 Android Profiler 中监控 Memory 内存 , 如果出现下图样式的内存图 , 说明出现了内存抖动 ;

    在这里插入图片描述





    六、 排查内存抖动



    内存抖动查找 , 直接跳转到 Android Profiler 界面 , 点击 Dump Java Heap 按钮 , 保存一份内存快照 , 找出消耗内存最多的对象 , Allocations 个数最多的对象的类 , 该类对象大概率就是造成内存抖动的原因 ;

    在这里插入图片描述





    七、 常见的造成内存抖动操作



    1. 日志打印 : 循环中使用 Log.i 函数打印日志 , 使用加号拼接字符串 , 尤其是每次拼接不同的字符串 , 每个字符串都需要创建释放 , 这样会造成内存抖动 ;


    2. 循环操作 : 在循环内频繁创建对象 , 与销毁对象 ; 尽量将创建对象操作放在成员级别 , 或放在循环体外部 ;





    八、 从内存优化角度选择集合



    HashMap 集合 : HashMap 有一个默认大小 , 还有一个扩容因子 ; 如默认大小 100 , 扩容因子 0.8 , 该集合只能存储了 80 个 , 之后如果还想向其中存储数据 , 就需要扩容 , 扩容时 , 直接在默认大小基础上翻倍 ;


    SparseArray 集合 : SparseArray 有默认大小 , 没有扩容因子 , 每次扩容 , 直接翻倍 ; SparseArray 的增删查改都要进行二分查找 ; SparseArray 的 Key 是 int 类型 , 其不必使用 Integer 包装类型 ; 数据量很大时 , 且需要键值对数据结构时 , 考虑使用 SparseArray 集合 ;

    展开全文
  • 1.为什么会内存抖动简单说就是在短时间内有大量的gc操作2.举个例子public class MainActivity extends AppCompatActivity {private String result = "";@Overrideprotected void onCreate(Bundle savedInstanceState...

    1.为什么会内存抖动

    简单说就是在短时间内有大量的gc操作

    2.举个例子

    public class MainActivity extends AppCompatActivity {

    private String result = "";

    @Override

    protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);

    setContentView(R.layout.activity_main);

    Button bt = (Button) findViewById(R.id.bt);

    //点击按钮进行字符串拼接操作

    bt.setOnClickListener(new View.OnClickListener() {

    @Override

    public void onClick(View view) {

    for (int i = 0; i < 1000000; i++) {

    result = result +i;

    }

    }

    });

    }

    }

    点击按钮进行字符串的拼接

    我们知道String 类型的变量是不变的

    比如

    String value1 = "a";//创建一个对象指向value1

    value1 = value1 + "b";//再次创建一个对象指向value1

    上面的例子循环了1000000次,就会创建1000000个对象,这么多对象创建出来又被回收势必会引起内存抖动,我们通过日志或者monitors可以分析出来

    com.dgtech.myapplication I/art: Background sticky concurrent mark sweep GC freed 26(864B) AllocSpace objects, 35(19MB) LOS objects, 18% free, 12MB/15MB, paused 5.530ms total 23.313ms

    com.dgtech.myapplication I/art: Background sticky concurrent mark sweep GC freed 31(1040B) AllocSpace objects, 41(23MB) LOS objects, 0% free, 76MB/76MB, paused 5.250ms total 40.184ms

    com.dgtech.myapplication I/art: Background partial concurrent mark sweep GC freed 114(3KB) AllocSpace objects, 159(104MB) LOS objects, 7% free, 50MB/54MB, paused 1.995ms total 107.696ms

    com.dgtech.myapplication I/art: Background partial concurrent mark sweep GC freed 36(1048B) AllocSpace objects, 42(29MB) LOS objects, 6% free, 59MB/63MB, paused 13.771ms total 57.703ms

    com.dgtech.myapplication I/art: Background sticky concurrent mark sweep GC freed 14(480B) AllocSpace objects, 17(12MB) LOS objects, 1% free, 15MB/15MB, paused 5.508ms total 12.141ms

    com.dgtech.myapplication I/art: Background sticky concurrent mark sweep GC freed 20(672B) AllocSpace objects, 27(19MB) LOS objects, 0% free, 16MB/16MB, paused 5.435ms total 19.526ms

    当有大量日志连续打印以上类似内容时,说明内存有抖动,我们需要检查代码,或者使用更直观的方式来看:

    acd82503a9e5

    Monitors

    从Monitors的监控来看,内存一开始是平稳的,当点击拼接字符串的按钮后变开始抖动

    注:有的时候我们无法选择要调试的程序,就像这样:

    acd82503a9e5

    异常情况

    这个时候我们需要选择tools - Android - Enable ADB Integration

    展开全文
  • 内存溢出,内存泄漏,内存抖动你都碰到过吗?怎么解决的?如何区分这几种情况?怎么解决由内存泄漏而导致的内存溢出? 内存优化 . 内存泄露 内存溢出 内存抖动 分析与解决 内存溢出和内存泄漏的区别、产生原因以及...

    内存溢出,内存泄漏,内存抖动你都碰到过吗?怎么解决的?如何区分这几种情况?怎么解决由内存泄漏而导致的内存溢出?

    内存优化 . 内存泄露 内存溢出 内存抖动 分析与解决

    内存溢出和内存泄漏的区别、产生原因以及解决方案

    一、内存溢出:

    (一)、定义:

    内存溢出 out of memory,是指程序在申请内存时,没有足够的内存空间供其使用,出现out of memory;比如申请了一个integer,但给它存了long才能存下的数,那就是内存溢出。

    (二)、引起内存溢出的原因以及解决方案:

    原因:

    1.内存中加载的数据量过于庞大,如一次从数据库取出过多数据;
    2.集合类中有对对象的引用,使用完后未清空,使得JVM不能回收;
    3.代码中存在死循环或循环产生过多重复的对象实体;
    4.使用的第三方软件中的BUG;
    5.启动参数内存值设定的过小

    解决方案:

    第一步,修改JVM启动参数,直接增加内存。(-Xms,-Xmx参数一定不要忘记加。)
    第二步,检查错误日志,查看“OutOfMemory”错误前是否有其它异常或错误。
    第三步,对代码进行走查和分析,找出可能发生内存溢出的位置。

    (三)、如何区分:

    报错:提示“out of memory”。

    二、内存泄漏:

    (一)、定义:

    内存泄露 memory leak,是指程序在申请内存后,无法释放已申请的内存空间,一次内存泄露危害可以忽略,但内存泄露堆积后果很严重,无论多少内存,迟早会被占光。

    (二)、引起内存泄漏的原因以及解决方案:

    Android如何有效地解决内存泄漏

    引起内存泄漏的场景:

    • 资源对象没关闭造成的内存泄漏,如查询数据库后没有关闭游标cursor
    • 构造Adapter时,没有使用 convertView 重用
    • 对象被生命周期长的对象引用,如activity被静态集合引用导致activity不能释放
    • Bitmap对象不再使用时,没有调用recycle()释放内存(?存在疑问)

    (三)、如何区分:

    内存泄露, 观察 momory monitor 出现,内存不断增加  然后降低.
    工具使用:通过 heap viewer 查看

    三、内存抖动:

    (一)、定义:

    内存抖动是指在短时间内有大量的对象被创建或者被回收的现象,内存抖动出现原因主要是频繁(很重要)在循环里创建对象。

    (二)、引起内存抖动的原因以及解决方案:

    内存抖动出现原因主要是频繁(很重要)在循环里创建对象,导致大量对象在短时间内被创建,由于新对象是要占用内存空间的而且是频繁,如果一次或者两次在循环里创建对象对内存影响不大,不会造成严重内存抖动这样可以接受也不可避免,频繁的话就很内存抖动很严重。内存抖动的影响是如果抖动很频繁,会导致垃圾回收机制频繁运行(短时间内产生大量对象,需要大量内存,而且还是频繁抖动,就可能会需要回收内存以用于产生对象,垃圾回收机制就自然会频繁运行了)。综上就是频繁内存抖动会导致垃圾回收频繁运行。

    (三)、如何区分:

    内存抖动: 通过momory monitor 发现 出现内存忽上忽下 形成针尖状的情况.

    展开全文
  • 在Java内存管理机制中我提到过内存抖动会引起频繁的GC,从而使UI线程被频繁阻塞,导致画面卡顿。这次我们就聊聊内存抖动。 需要避免内存抖动 内存抖动是由于短时间内有大量对象进出Young Generiation区导致的,它...

    参考资料

    Google官方讲解视屏

    背景介绍

    Java内存管理机制中我提到过内存抖动会引起频繁的GC,从而使UI线程被频繁阻塞,导致画面卡顿。这次我们就聊聊内存抖动。

    需要避免内存抖动

    内存抖动是由于短时间内有大量对象进出Young Generiation区导致的,它伴随着频繁的GC。通常存在内存抖动时,我们可以在Android StudioMonitors中看到如下场景: 内存抖动图 下面是避免发生内存抖动的几点建议:

    • 尽量避免在循环体内创建对象,应该把对象创建移到循环体外。
    • 注意自定义View的onDraw()方法会被频繁调用,所以在这里面不应该频繁的创建对象。
    • 当需要大量使用Bitmap的时候,试着把它们缓存在数组中实现复用。
    • 对于能够复用的对象,同理可以使用对象池将它们缓存起来。

    总结

    总之,因为内存抖动是由于大量对象在短时间内被配置而引起的,所以我们要做的就是谨慎对待那些可能会大量创建对象的情况。

    转载于:https://my.oschina.net/coorchice/blog/2999118

    展开全文
  • Android内存抖动

    2019-01-16 21:21:18
    在Java内存管理机制中内存抖动会引起频繁的GC,从而使UI线程被频繁阻塞。内存抖动是由于短时间内有大量对象进出Young Generiation区导致的。
  • Android 内存抖动

    2018-03-12 12:41:00
    内存抖动是指内存频繁的分配和回收内存,而频繁的gc会导致卡顿,严重时一样会导致OOM。Android 使用分代收集算法(主要使用CMS垃圾收集器),使用的标记清除算法,所以会产生内存碎片。检测优化内存抖动:运行app,...
  • 内存抖动:在短时间内有大量对象被创建或者被回收的现象,主要原因是频繁在循环里创建对象。 在程序里,每创建一个对象,就会有一块内存分配给它;每分配一块内存,程序的可用内存也就少一块;当程序被占用的内存...
  • 内存泄漏: 内存溢出: 内存抖动
  • 本文介绍了什么是内存泄漏、内存抖动以及内存溢出,并且给出了各自的优化方案。本文属于Android内存优化系列的一部分。
  • 内存抖动、内存泄漏与内存溢出 优化的结果:使得app流畅不卡 内存抖动 短时间内有大量对象创建与销毁,它伴随着频繁的GC。 比较典型的就是字符串的拼接造成内存抖动。 比如: String str = ""; for(int i=0; i< ...
  • 在开发App的过程中我们会经常遇到内存抖动或者内存泄露的问题,我们需要用一些常用的工具去定位这些问题 2.内存抖动 2.1定义 短时间内有大量对象创建销毁,它伴随着频繁的GC 2.2检测方式 : Profiler 例子 点击后创建...
  • 前言:应用开发后期会会对应用做性能优化,此时肯定会伴随内存抖动,内存泄漏,内存溢出等问题,此时就会对这些问题进行排查分析,记录一下这些问题的的本质,产生的原因,处理方法(LeakCanary) 本质 开发者在...
  • 1 Android内存抖动 内存抖动是指内存忽高忽低,有短时间内快速的上升和下落的趋势,内存呈锯齿状。此时会频繁的GC,造成卡顿,甚至有OOM的可能 内存抖动越剧烈,说明单次分配的内存更大。 2 内存抖动的定位 对于...
  • 内存优化--内存抖动

    千次阅读 2019-07-09 13:02:26
    内存抖动是指内存频繁的分配和回收, 而频繁的gc会导致卡顿, 严重时和内存泄漏一样会导致OOM 垃圾回收 在对对象进行回收前需要对垃圾进行采集, 不同的虚拟机实现可能使用不同的垃圾收集算法, 不同的手机算法的实现也...
  • 在开发大型app中,会遇到内存抖动的情况,什么是内存抖动呢,就是内存频繁的分配和回收,从而造成内存不稳定,内存不足及碎片,它有哪些表现呢 表现: 频繁GC,内存曲线呈现出来锯齿状 危害: 导致卡顿,OOM 解决方案 ...
  • 1. JVM内存泄漏与内存溢出的区别? 2. 内存抖动是什么?怎么解决? 3. 垃圾回收机制是什么样的?
  • 概念 内存泄漏:是代码逻辑错误导致的,本应该释放的对象,由于有强引用,导致其不能被垃圾回收器回收。可以看我写的另一篇文章内存泄露(Memory Leak) 内存溢出(OOM):需要内存,...内存抖动说明是在频繁的...
  • 内存抖动解决实战

    千次阅读 2019-04-12 15:30:54
    1、 2、 3、 ...Memory Profiler使用...进入到另一个页面后,可以看到界面呈锯齿状,可以初步判断出现了内存抖动,这种情况如果非常严重的话,也会导致卡顿,同时由于可用内存减少,可能导致OOM.此时,通过Me...
  • 内存抖动 短时间内有大量对象创建销毁,它伴随着频繁的GC。 比较典型的就是字符串的拼接造成内存抖动。 比如: String str = ""; for(int i=0; i<10; i++) { str += i; } +=操作会编译成StringBuilder,然后...
  • 内存抖动是指在短时间内有大量的对象被创建或者被回收的现象,内存抖动出现原因主要是频繁(很重要)在循环里创建对象(导致大量对象在短时间内被创建,由于新对象是要占用内存空间的而且是频繁,如果一次或者两次在...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,101
精华内容 440
关键字:

内存抖动