范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文

Android技术分享Android中部分内存泄漏示例及解决方案

  简单介绍内存泄漏&内存抖动
  内存泄漏:Memory leak, 是一种资源泄漏,主因是计算机程序对存储器配置管理失当,失去对一段已分配内存空间的控制,造成程序继续占用已经不再使用的内存空间,或是存储器所存储之对象无法透过执行代码而访问,令内存资源空耗。
  简单来说,内存泄漏是指无法正确回收已经不再使用的内存。
  举例:
  请注意以下的例子是虚构的在此例中的应用程序是一个简单软件的一小部分,用来控制电梯的运作。
  此部分软件当乘客在电梯内按下一楼层的按钮时运行。
  当按下按钮时:
  要求使用存储器,用作记住目的楼层
  把目的楼层的数字储存到存储器中
  电梯是否已到达目的楼层?
  如是,没有任何事需要做:程序完成
  否则:
  等待直至电梯停止
  到达指定楼层
  释放刚才用作记住目的楼层的存储器
  此程序有一处会造成存储器泄漏:如果在电梯所在楼层按下该层的按钮(即上述程序的第4步),程序将触发判断条件而结束运行,但存储器仍一直被占用而没有被释放。这种情况发生得越多,泄漏的存储器也越多。
  这个小错误不会造成即时影响。因为人不会经常在电梯所在楼层按下同一层的按钮。而且在通常情况下,电梯应有足够的存储器以应付上百次、上千次类似的情况。不过,电梯最后仍有可能消耗完所有存储器。这可能需要数个月或是数年,所以在简单的测试下这个问题不会被发现。
  而这个例子导致的后果会是不那么令人愉快。至少,电梯不会再理会前往其他楼层的要求。更严重的是,如果程序需要存储器去开启电梯门,那可能有人被困电梯内,因为电梯没有足够的存储器去开启电梯门。
  存储器泄漏只会在程序运行的时间内持续。例如:关闭电梯的电源时,程序终止运行。当电源再度开启,程序会再次运行而存储器会重置,而这种缓慢的泄漏则会从头开始再次发生。
  内存抖动
  源自Android文档中的Memory churn一词,中文翻译为内存抖动。
  指快速频繁的创建对象从而产生的性能问题。
  引用Android文档原文:垃圾回收事件通常不会影响应用的性能。不过,如果在短时间内发生许多垃圾回收事件,就可能会快速耗尽帧时间。系统花在垃圾回收上的时间越多,能够花在呈现或流式传输音频等其他任务上的时间就越少。
  通常,"内存抖动"可能会导致出现大量的垃圾回收事件。实际上,内存抖动可以说明在给定时间内出现的已分配临时对象的数量。
  例如,您可以在 `for` 循环中分配多个临时对象。或者,您也可以在视图的 `onDraw()` 函数中创建新的 `Paint` 或 `Bitmap` 对象。在这两种情况下,应用都会快速创建大量对象。这些操作可以快速消耗新生代 (young generation) 区域中的所有可用内存,从而迫使垃圾回收事件发生。
  内存泄漏(Memory leak)的产生和避免方式
  Java内存泄漏的根本原因是长生命周期的对象持有短生命周期对象的引用就很可能发生内存泄漏。
  尽管短生命周期对象已经不再需要,但因为长生命周期依旧持有它的引用,故不能被回收而导致内存泄漏。
  几种引起内存泄漏的问题:
  静态集合类引起的内存泄漏
  HashMap 、ArrayList 等集合以静态形式声明时,这些静态对象的生命周期与应用程序一致。他们所引用的对象也无法被释放,因为它们也被集合引用着。private static HashMap a = new HashMap(); public static void main(String args[]) { for (int i = 0; i < 1000; i++) { Object tO = new Object(); a.put("0", tO); tO = null; } }
  如果仅仅释放引用本身(tO = null),ArrayList 依然在引用该对象,GC无法回收。
  监听器
  在Java应用中,通常会用到很多监听器,一般通过addXXXXListener() 实现。但释放对象时通常会忘记删除监听器,从而增加内存泄漏的风险。
  各种连接
  如数据库连接、网络连接(Socket)和I/O连接。忘记显式调用close() 方法引起的内存泄漏。
  内部类和外部模块的引用
  内部类的引用是很容易被遗忘的一种,一旦没有释放可能会导致一系列后续对象无法释放。此外还要小心外部模块不经意的引用,内部类是否提供相应的操作去除外部引用。
  单例模式
  由于单例的静态特性,使其生命周期与应用的生命周期一样长,一旦使用不恰当极易造成内存泄漏。如果单利持有外部引用,需要注意提供释放方式,否则当外部对象无法被正常回收时,会进而导致内存泄漏。
  常见的内存泄漏处理方式:
  集合类泄漏
  如集合的使用范围超过逻辑代码的范围,需要格外注意删除机制是否完善可靠。比如由静态属性static 指向的集合。
  单利泄漏
  以下为简单逻辑代码,只为举例说明内存泄漏问题,不保证单利模式的可靠性。public class AppManager { private static AppManager instance; private Context context; private AppManager(Context context) { this.context = context; } public static AppManager getInstance(Context context) { if (instance == null) { instance = new AppManager(context); } return instance; } }
  AppManager 创建时需要传入一个Context ,这个Context 的生命周期长短至关重要。
  1. 如果传入的是Application 的Context ,因为Application 的生命周期等同于应用的生命周期,所以没有任何问题。
  2. 如果传入的是Activity 的Context ,则需要考虑这个Activity 是否在整个生命周期都不会被回收了,如果不是,则会造成内存泄漏。
  非静态内部类创建静态实例造成的内存泄漏public class MyActivity extends AppCompatActivity { private static MyInnerClass mInnerClass = null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ... if (mInnerClass == null) { mInnerClass = new MyInnerClass(); } } class MyInnerClass { ... } }
  内部类持有外部类引用,而static声明的对象声明周期通常会比Activity长。即使关闭这个页面,由于mInnerClass为静态的,并且持有MyActivity的引用,导致无法回收此页面从而引起内存泄漏。
  应该将该内部类单独封装为一个单例来使用。
  匿名内部类/异步线程public class MyActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ... new Thread(new Runnable() { @Override public void run() { ... } }).start(); } }
  Runnable都使用了匿名内部类,将持有MyActivity的引用。如果任务在Activity销毁前未完成,将导致Activity的内存无法被回收,从而造成内存泄漏。
  解决方法:将Runnable独立出来或使用静态内部类,可以避免因持有外部对象导致的内存泄漏。
  Handler造成的内存泄漏public class SampleActivity extends AppCompatActivity { private final Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { ... } } @Override protected void onCreate(Bundle savedInstanceState) { ... mHandler.postDelayed(new Runnable() { @Override public void run() { ... } }, 300000); finish(); } }
  Handler属于TLS(Thread Local Storage)变量,生命周期与Activity是不一致的,容易导致持有的对象无法正确被释放
  当Android应用程序启动时,该应用程序的主线程会自动创建一个Looper对象和与之关联的MessageQueue。
  当主线程中实例化一个Handler对象后,它就会自动与主线程Looper的MessageQueue关联起来。所有发送到MessageQueue的Messag都会持有Handler的引用,所以Looper会据此回调Handle的handleMessage()方法来处理消息。只要MessageQueue中有未处理的Message,Looper就会不断的从中取出并交给Handler处理。
  另外,主线程的Looper对象会伴随该应用程序的整个生命周期。
  在Java中,非静态内部类和匿名类内部类都会潜在持有它们所属的外部类的引用,但是静态内部类却不会。
  当该 Activity 被finish() 掉时,延迟执行任务的 Message 还会继续存在于主线程中,它持有该 Activity 的 Handler 引用,所以此时finish() 掉的 Activity 就不会被回收了从而造成内存泄漏(因 Handler 为非静态内部类,它会持有外部类的引用,在这里就是指 SampleActivity)。
  解决方法:在 Activity 中避免使用非静态内部类,比如上面我们将 Handler 声明为静态的,则其存活期跟 Activity 的生命周期就无关了。同时通过弱引用的方式引入 Activity,避免直接将 Activity 作为 context 传进去,见如下代码:public class SampleActivity extends AppCompatActivity { private static class MyHandler extends Handler { private final WeakReference mActivity; public MyHandler(SampleActivity activity) { mActivity = new WeakReference(activity); } @Override public void handleMessage(Message msg) { SampleActivity activity = mActivity.get(); if (activity != null) { ... } } } private final MyHandler mHandler = new MyHandler(this); private static final Runnable mRunnable = new Runnable() { @Override public void run() { ... } } @Override protected void onCreate(Bundle savedInstanceState) { ... mHandler.postDelayed(mRunnable, 300000); finish(); } }
  避免不必要的静态成员变量
  对于BroadcastReceiver、ContentObserver、File、Cursor、Stream、Bitmap等资源的使用,应在Activity销毁前及时关闭或注销。
  不使用WebView对象时,应调用`destroy()`方法销毁。

耳聋到何程度需要佩戴助听器?其实对于助听器的佩戴,一般建议如果是出现了一定程度听力损伤的情况下,还是需要尽早地佩戴,因为越早配戴对于听力的进一步下降具有明显的缓解作用。而在现实生活中,很多人可能觉得佩戴助听器有没有极力推荐的APP?你最爱的APP是什么?中国大学有top9,实用软件也有top9,这九款app堪称宝藏软件!我的桌面我的桌面是一款精致女孩必备的个性化绝美手机桌面定制软件。它功能强大,涵盖小组件主题壁纸三大功能。其中小组你的下一台笔记本,考虑换什么?欢迎在点击右上角关注太平洋电脑网,不定时放送福利哦!岁月催人老,电脑的性能迭代更加无情。三年花了大价钱买的顶配游戏笔记本,当时还信誓旦旦地宣称五年内性能不落伍,然而到了今年想用它一收评沪指跌超2险守3000点国产软件股领涨中国经济网北京5月6日讯今日三大指数大幅低开,随后全天维持低位震荡,沪指盘中一度失守3000点关口。板块方面,互联网电商板块国产软件股逆市大涨,新冠检测油气开采中药等板块走强机场航终于挖到了这个文字转换工具,独享近10种功能,也太能打了吧不上班不知道,原来干文字这方面的活这么累,在这里要特别点名一下做会议记录,全程低头狂写,最后还是落了一大截。想录个音吧,会后还得花大把时间去听,真的愁死人!今天就要给各位小伙伴分享恐龙的灭亡事件?恐龙灭绝没有确切的原因。主要有以下几种理论1大陆漂移说地质研究证明,在恐龙时代,地球上只有一个大陆,即潘加大陆。由于地壳的变化,该大陆在侏罗纪时期经历了一次大的分裂和漂移,最终导致中兴Axon40将至,4nm芯片坐镇,5000mAh1TB存储讨人喜欢中兴作为国产老品牌巨头,虽然现在的处境有些不景气,但在曾经的中华联酷时代,中兴也赫赫有名,拥有着较高较稳的市场份额占比。不过在这个风云变幻的智能手机市场,谁又能一直红火下去呢?如今电动车续航都是骗人的?4种测试一个比一个虚,到底谁最靠谱?4月,由于上海封城等因素影响,整个汽车市场都处在大跌的环境下,但新能源乘用车却还能零售28。2万辆,同比暴增78。5。不管你信不信,新能源大趋势已经到来。很多人对新能源车的痛点是,抖音热卖的智能手表质量堪忧笔者在看头条视频的时候,被抖音视频广告吸引,购买了一只智能手表M2pro智能通话语音手表。购买不到半年竟然手表电池发生严重衰减,充满电不到3小时开始显示没电,根本没法正常戴啊。我滴京东发布2022春节消费观察,山东成交额居全国第五日前,京东发布的春节消费趋势显示,截至2月5日,2022春节期间成交额同比增长超50,其中,山东在春节期间的成交额排全国各省市第五位,前四位是广东江苏北京四川。此外,河南江西西藏湖春节假期全国共揽收投递快递包裹7。49亿件来源国家邮政局国家邮政局监测数据显示,今年春节期间(1月31日至2月6日),全国邮政快递业共揽收和投递快递包裹7。49亿件,较去年农历同期增长16,邮政快递传递亲情温暖人心的作用进
快手电商下架朵唯中兴索爱等12个手机品牌6月2日消息,近日,直播主播在快手电商销售朵唯山寨机引发了不少网友的关注。对此,快手官方发布声明回应,并下架朵唯中兴索爱等12个手机品牌。据了解,近日,有一互联网博主称快手主播驴嫂小米手机新专利曝光带圆形弹出式摄像头,撞车OPPO去年类似专利小米手机新专利曝光带圆形弹出式摄像头!近年来小米成立了手机相机部并投入了大量资金,取得的效果也是显而易见。除了率先上了一亿像素摄像头外,在DXO相机排行榜上也是多次拿下全球第一。可全面屏的又一解决方案小米旋转前置双摄专利图曝光如今,各大厂商为了真全面屏想出了各种千奇百怪的解决方案,比如弹出式摄像头滑盖屏下摄像头等等。最近,小米的一项专利图曝出,在正面,这款手机采用无孔全面屏,夺人眼球的是它的前摄部分采用比特币为什么在那么多国家禁止后反而升值那么快呢?比特币被禁的国家主要是新兴市场国家,如中国,印度,土耳其等。所谓的禁止也是禁止投机交易控制风险等,外加这些国家本来就对数字货币的使用和交易管制很大因此对币价影响有限。反之,如果禁令价格跌至新低,号称跳水王的三星Note20Ultra值得入手吗?Note8用了两年,现在用的note10也近两年了,虽然是手机app重度爱好者,但从没体会过其他人说的卡顿,下一个换机的目标就是20U。除了系统之外,外观也很喜欢,方中带柔,裸机手iPhoneXR全新版本上架,不带充电器,售价3999元起一直以来,新产品上架旧产品下架是亘古不变的道理,尤其是手机产品,更是如此。而让人意外的是,近期消息显示,苹果竟然重新上架了3年前的iPhoneXR,并且也是跟随iPhone12系列华为发布鸿蒙手机百款设备将启动升级中新社北京6月2日电(记者刘育英)北京时间6月2日晚,华为正式发布鸿蒙HarmonyOS2及多款搭载HarmonyOS2的新产品,华为手机平板等百款设备将陆续启动HarmonyOS快手在微信端上线本地生活小程序吃喝玩乐在快手蓝鲨早报1快手在微信端上线本地生活小程序吃喝玩乐在快手快手在微信端同样上线了一款可以团购的微信小程序,名为吃喝玩乐在快手。该小程序是一个纯粹的团购平台,并没有加入短视频的属性。值得注意的是一款可能性的表?搭载HarmonyOS的华为Watch3体验分享作为一个华为WATCHGT2Pro的用户,是怎么看待华为WATCH3的?为什么把表壳右侧的上下按钮改成了上表冠,下按钮的设计?在使用中有什么改进之处和亮眼功能?我会在下文一一分享自赶上了!华为鸿蒙商标获转让,发布会可以挺直腰板了今日,手机圈里都在为华为鸿蒙商标获转让这则好消息欢呼雀跃。据悉,注册号38307327号鸿蒙商标已被惠州市契贝科技有限公司转让于华为技术有限公司,包括HONGMENG商标。据企查查日产开发出可紧急避让连环事故的自动驾驶技术日经新闻4月26日报道,日产汽车4月25日宣布,作为自动驾驶的一环,开发了可紧急避让连环事故等复杂事态的技术。搭载新一代传感器LiDAR等,利用自主开发的算法实时掌握周围情况。日产