内存溢出

内存溢出(OutofMemory):系统会给每个APP分配内存也就是HeapSize值。当APP占用的内存加上我们申请的内存资源超过了Dalvik虚拟机的最大内存时就会抛出的OutOfMemory异常。
内存泄漏(MemoryLeak):当一个对象不在使用了,本应该被垃圾回收器(JVM)回收。但是这个对象由于被其他正在使用的对象所持有,造成无法被回收的结果。内存泄漏最终会导致内存溢出。内存泄露的主要原因:长生命周期对象持有短生命周期对象。
内存抖动:内存抖动是指在短时间内有大量的对象被创建或者被回收的现象,主要是循环中大量创建、回收对象。这种情况应当尽量避免。
它们三者的重要等级分别:内存溢出>内存泄露>内存抖动。
内存溢出对我们的App来说,影响是非常大的。有可能导致程序闪退,无响应等现象,因此,我们一定要优先解决OOM的问题。

查询某个应用的内存情况

adb shell dumpsys meminfo pgk
Applications Memory Usage (in Kilobytes):
Uptime: 452183367 Realtime: 1104572907** MEMINFO in pid 2518 [com.android.systemui] **Pss  Private  Private  SwapPss      Rss     Heap     Heap     HeapTotal    Dirty    Clean    Dirty    Total     Size    Alloc     Free------   ------   ------   ------   ------   ------   ------   ------Native Heap    52100    51944      132     1144    55188    76948    35459    28523Dalvik Heap    14195    14108        0        4    22048    50307    12577    37730Dalvik Other    11627     4660       12      148    21400                           Stack     1888     1888        0       40     1904                           Ashmem       57       48        0        0      560                           Gfx dev     5264     5264        0        0     5264                           Other dev       93        0       88        0      456                           .so mmap     3243      284        8       48    36456                           .jar mmap     1229        0      288        0    29248                           .apk mmap    16146        0    12740        0    29624                           .ttf mmap      275        0      188        0      588                           .dex mmap      312      104      200        0      688                           .oat mmap       45        0        0        0     3820                           .art mmap     4223     4052        0       68    19480                           Other mmap      274       40       92        0     1700                           EGL mtrack    36864    36864        0        0    36864                           GL mtrack      384      384        0        0      384                           Unknown     1106     1104        0       16     1720                           TOTAL   150793   120744    13748     1468   267392   127255    48036    66253App SummaryPss(KB)                        Rss(KB)------                         ------Java Heap:    18160                          41528Native Heap:    51944                          55188Code:    13812                         115444Stack:     1888                           1904Graphics:    42512                          42512Private Other:     6176System:    16301Unknown:                                   10816TOTAL PSS:   150793            TOTAL RSS:   267392       TOTAL SWAP PSS:     1468ObjectsViews:     1741         ViewRootImpl:        7AppContexts:       55           Activities:        0Assets:       57        AssetManagers:        0Local Binders:      349        Proxy Binders:      118Parcel memory:       26         Parcel count:      106Death Recipients:       11      OpenSSL Sockets:        0WebViews:        0SQLMEMORY_USED:        0PAGECACHE_OVERFLOW:        0          MALLOC_SIZE:        0

其中,需要重点关注的字段有:
NativeHeap:Native代码分配的内存,虚拟机和Android框架分配内存
DalvikHeap:Java对象分配的占据内存。
DalvikOther:类数据结构和索引占据内存。
PSS:Proportional Set Size,记录了实际使用的物理内存(比例分配共享库占用的内存),表示一个进程在 RAM 中实际使用的空间地址大小,它按比例包含了共享库占用的内存。假如有3个进程使用同一个共享库,那么每个进程的 PSS 就包括了 1/3 大小的共享库内存。这种方式表示进程的内存使用情况较准确,但当只有一个进程使用共享库时,其情况和RSS一模一样。当一个进程被销毁时,其占用的那部分PSS又会被按比例地分配给其余使用这些库的进程。
RSS:Resident Set Size 实际使用物理内存(包含共享库占用的内存)。
注:Android系统对DalvikHeap有限制。

应用内存上限

可以通过 adb shell getprop dalvik.vm.heapgrowthlimit 获得应用内存上限
同理,还用相似方法得到下面信息

# 应用内存上限
adb shell getprop dalvik.vm.heapgrowthlimit
# 初始堆大小
adb shell getprop dalvik.vm.heapstartsize
# heapsize 表示不受控情况下的极限堆,表示单个虚拟机或单个进程可用的最大内存,如果存在heapgrowthlimit参数,则以heapgrowthlimit为准.
adb shell getprop dalvik.vm.heapsize

dalvik.vm.heapstartsize:它表示堆分配的初始大小,它会影响到整个系统对 RAM 的使用程度,和第一次使用应用时的流畅程度。它值越小,系统 RAM 消耗越慢,但一些较大应用一开始不够用,需要调用 gc 和堆调整策略,导致应用反应较慢。它值越大,这个值越大系统 RAM 消耗越快,但是应用更流畅。
dalvik.vm.heapgrowthlimit:单个应用可用最大内存,超出就会报 OOM。(仅针对 dalvik 堆,不包括native 堆)
dalvik.vm.heapsize:heapsize 表示不受控情况下的极限堆,表示单个虚拟机或单个进程可用的最大内存在设置了 heapgrowthlimit 的情况下,单个进程可用最大内存为 heapgrowthlimit 值。在 android 开发中,如果要使用大堆,需要在manifest 中指定 android:largeHeap 为 true,这样 dvm heap 最大可达 heapsize。

垃圾回收

垃圾标记算法

  1. 引用计数法:某个对象被引用时,它的引用计数器就+1,不被引用时,引用计数器就 -1,那些引用计数器为 0 的对象就是被标记为垃圾的对象。目前的主流 JAVA 虚拟机并没有使用该算法。因为它无法解决对象循环引用的问题
  2. 根搜索算法:选定一些对象作为 CG Roots,向下搜索,如果某个对象是从 CG Roots 向下搜索可达的,则认为不可回收。若某个对象从 CG Roots 向下搜索不可达,则认为可被回收

可作为 CG roots 的对象:

  1. 虚拟机栈中引用的对象;
  2. 方法区中类静态属性引用的对象;
  3. 方法区中常量引用的方法;
  4. 本地方法区中JNI(Native方法)引用的对象。

四种引用:强软弱虚

  1. 强引用:重要且必要。Java 虚拟机宁愿抛出 OutOfMemoryError 错误,使程序异常终止,也不会靠随意回收具有强引用的对象来解决内存不足问题。示例:Object object=new Object();
  2. 软引用:重要但不必要。如果内存空间足够,垃圾回收器就不会回收它,如果内存空间不足了,就会回收这些对象的内存。对应类:SoftReference
  3. 弱引用:不重要也不必要。只具有弱引用的对象拥有更短暂的生命周期。在垃圾回收器线程扫描它 所管辖的内存区域的过程中,一旦发现了只具有弱引用的对象,不管当前内存空间足够与否,都会回收它的内存。对应类:WeakReference
  4. 虚引用:形同虚设,与其他几种引用都不同,虚引用并不会决定对象的生命周期。如果一个对象仅持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收。对应类:PhantomReference

引用队列 ReferenceQueue

当 SoftReference 、WeakReference 与 PhantomReference 所引用的对象被回收时,该引用对象(注意是 Reference 对象而不是 Reference 对象所引用的对象)就会被添加到 ReferenceQueue 引用队列中,这样我们就可以知道哪些对象被回收了
以 WeakReference 使用为例
ReferenceQueue referenceQueue = new ReferenceQueue<>();
WeakReference<byte[]> weakReference = new WeakReference<byte[]>(bytes, referenceQueue);

弱散列表 WeakHashMap

WeakHashMap,此种 Map 的特点是,当除了自身有对 key 的引用外,此 key 没有其他引用那么此 map 会自动丢弃此值,所以比较适合做缓存。
其实现原理为:使用 WeakReference 当作key来进行数据的存储,当 key 中的引用被回收掉之后,该 WeakReference 会被添加到 ReferenceQueue 中,当使用 WeakHashMap 时,WeakHashMap 会将 检索 ReferenceQueue 中的 key 对象,如果某一个 key 存在于 ReferenceQueue 则将其与对应的 value 一并删除

Android 内存溢出、垃圾回收、四种引用相关推荐

  1. 垃圾回收之如何判断对象可以回收、四种引用以及实际案例操作

    垃圾回收 JVM内存结构中的堆存在垃圾回收机制,我们接下来就来详细地学习一下垃圾回收的相关知识. 1. 如何判断对象可以回收 1.1 引用计数法 只要一个对象被其他变量所引用,那就让这个对象的计数+1 ...

  2. Java 中的四种引用及垃圾回收策略

    Java 中有四种引用:强引用.软引用.弱引用.虚引用: 其主要区别在于垃圾回收时是否进行回收: 1.强引用 使用最普遍的引用.如果一个对象具有强引用,那就 类似于必不可少的生活用品,垃圾回收器绝不会 ...

  3. Java对象的生命周期与垃圾回收以及四种引用

    转载请注明出处: Java对象的生命周期 与 垃圾回收 - ITeye博客 - 老Man 创建对象的方式 用new语句创建对象. 使用反射,调用java.lang.Class或java.lang.re ...

  4. JVM学习笔记之四 四种引用和垃圾回收的两次标记

    四种引用和两次标记 四种引用 java中的数据类型我们知道是分为基本数据类型和引用类型的.基本数据类型是8种,分别是boolean byte short int long double float c ...

  5. 通过强弱软虚四种引用进一步了解垃圾回收机制

    在Java对象里,有强弱软虚四种引用,它们都和垃圾回收流程密切相关,在项目里,我们可以通过合理地使用不同类型的引用来优化代码的内存使用性能. 指向通过new得到的内存空间的引用叫强引用.比如有Stri ...

  6. java对象什么时候回收_Java对象的生命周期与垃圾回收以及四种引用

    创建对象的方式用new语句创建对象. 使用反射,调用java.lang.Class或java.lang.reflect.Constructor的newInstance()实例方法. 调用对象的clon ...

  7. JVM day03 四种引用 垃圾回收

    JVM day03 如何判断对象可以回收 引用计数法 一旦相互持有引用,就导致对象永远没法被回收. jvm并没有采用这种算法. 可达性分析算法 由GC Root出发,开始寻找,看看某个对象是否可达,如 ...

  8. java 四种内存_不可访问内存 Java四种引用包括强引用,软引用,弱引用,虚引用...

    小结: 1.不可访问内存是指一组没有任何可访问指针指向的由计算机程序进行动态分配的内存块. 2.垃圾收集器能决定是否一个对象还是可访问的:任何被确定不可访问的对象将会被释放. https://zh.w ...

  9. JVM上篇:内存与垃圾回收篇十四--垃圾回收器

    JVM上篇:内存与垃圾回收篇十四–垃圾回收器 1. GC分类与新能指标 1.1 垃圾回收器概述 垃圾收集器没有在规范中进行过多的规定,可以由不同的厂商.不同版本的JVM来实现. 由于JDK的版本处于高 ...

最新文章

  1. Android ADB Server启动失败
  2. 简单的php服务文件下载,php文件下载
  3. 01-spring配置详解
  4. 局域网Ubuntu与WinXP实现文件共享
  5. 训练日志 2019.4.14
  6. 70进货卖100利润是多少_服装批发利润大揭秘!让你拿货砍价心里有个底
  7. 程序员吐槽:组里新来一个“加班狂”,可把大家害惨了
  8. 金融文本信息情感分析(负面及主体判定)
  9. 有关label标签和单选按钮的注意事项
  10. 安装包时后面的参数以及简写
  11. 按键精灵手机助手旋转验证码上传插件
  12. ai作诗——分享好用人工智能作诗工具
  13. 苹果雪豹操作系统正式版_别着急更新!苹果 iOS 14 正式版导致部分游戏崩溃
  14. 苹果计算机音频无法使用,解决Mac电脑直播没有电脑内声音的问题
  15. 51单片机系列--蜂鸣器
  16. EXCEL如何将平均值加减标准差设置为科学计数法显示
  17. 信息流推广与普通搜索推广的区别与优势是什么?
  18. 南京信息工程大学计算机考研资料汇总
  19. mysql 100w 查询耗时4秒_MySql百万数据0秒筛选查询
  20. 手机屏幕如何投屏到电脑上(Windows10)

热门文章

  1. IPv4与IPv6之间的区别
  2. MMA9553L/MMA955L 计步器快速使用指南
  3. AFNetworking 返回3840
  4. Dynamodb基础操作
  5. 中国大学MOOC C语言程序设计(大连理工大学) 课后编程题 第三周题解(个人向仅供参考)
  6. Authorware自制拼图游戏
  7. AM2120单总线温湿度传感器移植与应用
  8. word段落每行首字怎么对齐_Word段落首行左右缩进及五种对齐方式
  9. Error(1.0.5 1107071739): D:\SAE_SDK_Windows_1.0.5\apps\/divjs/1/config.yaml is not existed解决方法...
  10. UT-Exynos4412 三星ARM四核旗舰开发平台android4.0体验-13串口功能调试