Android面试相关—内存溢出 内存泄漏 以及 冷启动的相关问题

oom 内存溢出 out of memary

1.什么是内存溢出

当前占用内存加上我们申请的内存资源超过了虚拟机最大的内存限制就会抛出out of memary的异常

2.一些容易混淆的概念

内存溢出:分配的内存不足以让你做一些操作

内存抖动:我们在短时间内创造了大量对象,然后马上会被释放 瞬间产生的对象严重占用了内存区

内存泄漏:某个不再使用的对象,由于被回收的时候,被其他的实例引用,导致不能被GC回收,从而无法释放,而造成内存泄漏

3.解决OOM(内存溢出)

1) bitmap的优化

    ①图片显示:在我们加载图片的时候,不要加载网络请求的图,而是判断 当页面停止滑动的时候,我们再进行加载网络请求的图片

    ②及时释放内存

    ③图片压缩:我们在加载网络图片的时候,可能那个图片特别大,超出了我们所分配的内存的大小,这个时候我们就要进行图片的压缩,对bitmap的大小进行控制,在加载图片之前,计算好占用内存的大小,然后再进行图片加载

  ④inBitmap()属性: 它可以提高Android系统中bitmap的使用效率

  2).捕获异常:为了避免应用在分配Bitmap中内存的时候出现oom,所以在实例化bitmap的时候,捕获一下oom的异常,而我们在开发过程中,我们大多数捕获的都是 exception,但对于oom来说,如果捕获exception是捕获不到的,因为out of memary error 是个错误,不是异常

  3).listview:convertView/lru 在listview中,我们要使用lru来缓存大图bitmap,三级缓存机制

  4).避免在onDrow方法中执行对象的创建,如果频繁调用对象创建,就会使内存突然上升,而在释放的时候,又会造成频繁的GC,这样就会造成内存抖动的现象,而内存抖动累计到一定程度的时候,也会造成oom

  5).谨慎使用多进程

4、如何检测内存问题?

1. 用Android Studio自带的Android Profitler找到MEMORT这个栏目进行检测.

2. LeakCanay(会找到并修复内存泄漏将OOM崩溃机率降低%94)


内存泄漏(不是直接可见的 是个独立活动的)

1.如何检测内存泄漏

借助LeakCanarz、MATMAT是一款强大的内存分析工具Square开源的一款轻量第三方内存泄漏检测工具

2.内存泄漏VS内存溢出的区别、二者关系

内存溢出:超出了虚拟机分配的内存内存泄漏:某个不再使用对象由于被其他实例引用

内存泄漏:当前占用内存加上我们申请的内存资源超过了虚拟机最大的内存限制

二者关系:内存泄漏可能会造成内存溢出,一旦内存泄漏非常严重,而导致垃圾回收无法回收对象,垃圾对象占用内存空间会越来越高,其他对象分配的内存分配的内存越来越小,而导致内存溢出

3.为什么会有内存泄漏

当一个对象不再被用的时候,GC无法回收,被其他实例引用着

4.内存泄漏的原因以及解决方案

1).单例 重复创建对象时要用到的

原因:单例的context静态特性使得生命周期和应用的生命周期一样长,当对象不再需要  时,单例对象还持有对象的应用,造成对象不能被正常回收,这就导致内存泄漏

解决方案:用Application的context,这样做保证了单例的生命周期和Application的生命周期一样长,就防止内存泄漏的产生

2).Handler造成的内存泄漏

原因:当Activity退出时,消息队列中还有未处理的消息或者正在处理的消息,消息队列中的message持有handler实例的引用导致内存资源无法及时回收

解决方案:创建静态内部类,对handler持有的对象是用弱引用,在Activity的Destroy或者stop时移除消息队列中的消息

根本原因:Handler和 activity 的生命周期长度不同

3).线程引起内存泄漏

原因:如果使用的是匿名内部类,对当前的Activity都有一个隐式调用如果Activity在销毁之前,任务还没有完成(里面的耗时操作),就会导致Activity的内存资源无法回收

解决方案:使用静态内部类的方式来避免内存泄漏,同时 在Activity销毁的时候,取消AcsynTask的任务,也能避免内存泄漏,又可以减少我们的资源

4).webView引起的内存泄漏

原因:如果webView解析页面的时候,页面数据较为复杂,就会占用好多内存,那么,当打开新页面的时候,为了快速回退,那之前的页面占用的内存不会被释放,那当加载较多网页的时候,就会导致系统不堪重负,从而使应用强行关闭

解决方案:webView放到单独的线程当中,当检测到占用的内存过大,我们就干掉它

5).非静态内部类创建静态实例

原因:这样就在Activity内部创建了一个非静态内部类的单例,每次启动Activity时都会使用该单例的数据,这样虽然避免了资源的重复创建,不过这种写法却会造成内存泄漏

解决方法:将其抽取出来封装成一个单例

6).动画

原因:无限循环动画  耗时操作  动画还没有执行完 持有activity的引用

解决方法:ondestroy中调用cancel()来停止动画

7).第三方库使用不当

原因:对于EventBus,RxJava等一些第三开源框架的使用,若是在Activity销毁之前没有进行解除订阅将会导致内存泄漏



#冷启动优化

一.什么是冷启动

1.冷启动的定义

冷启动就是在启动前,系统中没有该应用的任何进程信息时候启动应用就叫冷启动

2.冷启动/热启动的区别

热启动:就是冷启动启动之后,用户使用返回键退出应用,然后马上又重新启动应用

3.冷启动时间的计算

这个时间值从应用启动(创建进程)开始计算,到完成视图的第一次绘制(即Activity内容对用户可见)为止

二.冷启动流程

Ztfite进程中fork创建出一个新的进程

创建和初始化Application类、创建MainActivity类

inflate布局、当onCreate/onStart/onResume方法都走完

contenview的measure/layout/draw显示在页面上

三.如何对冷启动的时间进行优化

1.减少onCreate()方法的工作量

2.不要让Application参与业务的操作

3.不要在Application进行耗时操作

4.不要以静态变量的方式在Application 中保存数据

5.布局/mainThread,尽量减少布局的复杂度

#其他优化

一.android中不用静态变量存储数据

1.静态变量等数据由于进程已经被杀死而被初始化

2.使用其他数据传输方式:文件/sp/contentProvider

二.有关sp的安全问题

1.不能跨进程同步

2.存储Sharepreference的文件过大问题

三.内存对象序列化

序列化:将对象的状态信息转换为可以存储或传输的形式的过程

1.Serializeble

在序列化的时候会产生大量的临时变量,从而引起频繁的垃圾回收,会造成ui卡顿,内存抖动,甚至会造成内存溢出

2.Parcelable

总结:

(1)Serializeble是java的序列化方式,Parcelable是Android特有的序列化方式

(2)在使用内存的时候,Parcelable比Seriablizable性能高

(3)Serializable在序列化的时候会产生大量的临时变量,从而引起频繁的gc

(4)Parcelable不能使用在要将数据存储在磁盘上的情况

四.避免在ui线程中做繁重的操作

你可能感兴趣的:(Android面试相关—内存溢出 内存泄漏 以及 冷启动的相关问题)