基础知识记录:OOM异常出现的情况与处理方式
2017-07-03 20:25
399 查看
1、 查询内存情况
:通过Android Studio的Memory Monitor查看内存中Dalvik Heap的实时变化
2、 异常出现的情况
:当之前分配的内存+新分配的内存超出系统分配的内存时即 getMemoryClass()获取到的内存数据时就超出了内存,出现OOM
3、 异常出现的原因
:1、无限循环;
2、加载的图片过大或者图片过多;
3、无限制创建各种对象;
4、等
4、 异常处理方法
:1、减少对象的使用,尽量使用轻量级的(使用更加轻量的数据结构、少使用静态与枚举等)
2、使用图片是可进行压缩(大小、质量压缩),使用3级缓存机制,使用LRU的机制来缓存处理好的Bitmap图片,减少内存的付出
3、listview与gridview、recyclerview等加载数据时,使用convertView进行复用。
4、一些系统自带的资源,尽量使用系统的,可以减小内存,也能减小apk的大小。
知识点:LRU机制
计算机中有一个概念,我们用缓存来存放以前读取的数据,而不是直接丢掉,这样,再次读取的时候,可以直接在缓存里面取,而不用再重新查找一遍,这样系统的反应能力会有很大提高。但是,当我们读取的个数特别大的时候,我们不可能把所有已经读取的数据都放在缓存里,毕竟内存大小是一定的,我们一般把最近常读取的放在缓存里(相当于我们把最近联系的朋友的姓名和电话放在大脑里一样)。现在,我们就来研究这样一种缓存机制。
LRU缓存利用了这样的一种思想。LRU是Least Recently Used 的缩写,翻译过来就是“最近最少使用”,也就是说,LRU缓存把最近最少使用的数据移除,让给最新读取的数据。而往往最常读取的,也是读取次数最多的,所以,利用LRU缓存,我们能够提高系统的performance.
实现:
要实现LRU缓存,我们首先要用到一个类 LinkedHashMap。 用这个类有两大好处:一是它本身已经实现了按照访问顺序的存储,也就是说,最近读取的会放在最前面,最最不常读取的会放在最后(当然,它也可以实现按照插入顺序存储)。第二,LinkedHashMap本身有一个方法用于判断是否需要移除最不常读取的数,
其中实现方式可使用双链表 + hashtable来实现
:通过Android Studio的Memory Monitor查看内存中Dalvik Heap的实时变化
2、 异常出现的情况
:当之前分配的内存+新分配的内存超出系统分配的内存时即 getMemoryClass()获取到的内存数据时就超出了内存,出现OOM
3、 异常出现的原因
:1、无限循环;
2、加载的图片过大或者图片过多;
3、无限制创建各种对象;
4、等
4、 异常处理方法
:1、减少对象的使用,尽量使用轻量级的(使用更加轻量的数据结构、少使用静态与枚举等)
2、使用图片是可进行压缩(大小、质量压缩),使用3级缓存机制,使用LRU的机制来缓存处理好的Bitmap图片,减少内存的付出
3、listview与gridview、recyclerview等加载数据时,使用convertView进行复用。
4、一些系统自带的资源,尽量使用系统的,可以减小内存,也能减小apk的大小。
知识点:LRU机制
计算机中有一个概念,我们用缓存来存放以前读取的数据,而不是直接丢掉,这样,再次读取的时候,可以直接在缓存里面取,而不用再重新查找一遍,这样系统的反应能力会有很大提高。但是,当我们读取的个数特别大的时候,我们不可能把所有已经读取的数据都放在缓存里,毕竟内存大小是一定的,我们一般把最近常读取的放在缓存里(相当于我们把最近联系的朋友的姓名和电话放在大脑里一样)。现在,我们就来研究这样一种缓存机制。
LRU缓存利用了这样的一种思想。LRU是Least Recently Used 的缩写,翻译过来就是“最近最少使用”,也就是说,LRU缓存把最近最少使用的数据移除,让给最新读取的数据。而往往最常读取的,也是读取次数最多的,所以,利用LRU缓存,我们能够提高系统的performance.
实现:
要实现LRU缓存,我们首先要用到一个类 LinkedHashMap。 用这个类有两大好处:一是它本身已经实现了按照访问顺序的存储,也就是说,最近读取的会放在最前面,最最不常读取的会放在最后(当然,它也可以实现按照插入顺序存储)。第二,LinkedHashMap本身有一个方法用于判断是否需要移除最不常读取的数,
其中实现方式可使用双链表 + hashtable来实现
1. public class LRUCache { 2. 3. private int cacheSize; 4. private Hashtable<Object, Entry> nodes;//缓存容器 5. private int currentSize; 6. private Entry first;//链表头 7. private Entry last;//链表尾 8. 9. public LRUCache(int i) { 10. currentSize = 0; 11. cacheSize = i; 12. nodes = new Hashtable<Object, Entry>(i);//缓存容器 13. } 14. 15. /** 16. * 获取缓存中对象,并把它放在最前面 17. */ 18. public Entry get(Object key) { 19. Entry node = nodes.get(key); 20. if (node != null) { 21. moveToHead(node); 22. return node; 23. } else { 24. return null; 25. } 26. } 27. 28. /** 29. * 添加 entry到hashtable, 并把entry 30. */ 31. public void put(Object key, Object value) { 32. //先查看hashtable是否存在该entry, 如果存在,则只更新其value 33. Entry node = nodes.get(key); 34. 35. if (node == null) { 36. //缓存容器是否已经超过大小. 37. if (currentSize >= cacheSize) { 38. nodes.remove(last.key); 39. removeLast(); 40. } else { 41. currentSize++; 42. } 43. node = new Entry(); 44. } 45. node.value = value; 46. //将最新使用的节点放到链表头,表示最新使用的. 47. moveToHead(node); 48. nodes.put(key, node); 49. } 50. 51. /** 52. * 将entry删除, 注意:删除操作只有在cache满了才会被执行 53. */ 54. public void remove(Object key) { 55. Entry node = nodes.get(key); 56. //在链表中删除 57. if (node != null) { 58. if (node.prev != null) { 59. node.prev.next = node.next; 60. } 61. if (node.next != null) { 62. node.next.prev = node.prev; 63. } 64. if (last == node) 65. last = node.prev; 66. if (first == node) 67. first = node.next; 68. } 69. //在hashtable中删除 70. nodes.remove(key); 71. } 72. 73. /** 74. * 删除链表尾部节点,即使用最后 使用的entry 75. */ 76. private void removeLast() { 77. //链表尾不为空,则将链表尾指向null. 删除连表尾(删除最少使用的缓存对象) 78. if (last != null) { 79. if (last.prev != null) 80. last.prev.next = null; 81. else 82. first = null; 83. last = last.prev; 84. } 85. } 86. 87. /** 88. * 移动到链表头,表示这个节点是最新使用过的 89. */ 90. private void moveToHead(Entry node) { 91. if (node == first) 92. return; 93. if (node.prev != null) 94. node.prev.next = node.next; 95. if (node.next != null) 96. node.next.prev = node.prev; 97. if (last == node) 98. last = node.prev; 99. if (first != null) { 100. node.next = first; 101. first.prev = node; 102. } 103. first = node; 104. node.prev = null; 105. if (last == null) 106. last = first; 107. } 108. /* 109. * 清空缓存 110. */ 111. public void clear() { 112. first = null; 113. last = null; 114. currentSize = 0; 115. } 116. 117. } 118. 119. class Entry { 120. Entry prev;//前一节点 121. Entry next;//后一节点 122. Object value;//值 123. Object key;//键 124. }
相关文章推荐
- Java基础知识强化之IO流笔记02:try...catch的方式处理异常
- Android 加载打图片出现OOM异常的处理方式
- Java基础知识强化之IO流笔记03:throws的方式处理异常
- java异常处理基础知识
- 11级_Java_曹建波4.24 异常处理的基础知识
- C#基础知识梳理系列十:异常处理 System.Exception
- Python基础知识(三)--基本的异常处理、算术运算符、输入/输出
- C#基础知识梳理系列十:异常处理 System.Exception
- Java基础知识3:异常处理,数组与常用类
- android基础知识03——事件处理01:主要事件及其处理方式
- 异常处理基础知识
- java基础知识记录--异常 (摘自张孝祥整理java面试题)
- android基础知识24:Android中处理崩溃异常
- Java基础<异常机制>总结(异常体系、Exception特点、异常处理方式)
- java基础入门----IO异常处理方式
- Android3.0版本以上出现android.os.NetworkOnMainThreadException异常与处理方式
- Android在处理图片减少出现OOM的方式
- 在jsp中出现异常后应该停止往下执行的情况,怎么处理?
- 抽取时出现有交易记录而无会员的情况处理
- Python基础知识(三)--基本的异常处理、算术运算符、输入/输出