面试题收集

166 阅读3分钟

分析卡顿发生在什么函数,资源占用情况的方法

  • 利用UI线程的Looper打印的日志匹配

    Looper比较适合在发布前进行测试或者小范围灰度测试然后定位问题

  • 使用Choreographer.FrameCallback

    是否监控线上环境的App的掉帧情况来计算app在某些场景的流畅度然后针对性的做性能优化.

Android 系统为每个应用分配的内存规则

  • app启动分配的初始化内存大小是16M
  • 系统分配单个app堆内存的最大显示为192M,超过就会OOM内存溢出
  • 如果在清单文件中Application添加largeHeap属性后,耽搁APp堆内存的最大值为512M

产生OOM的原因

  • java堆内存溢出
  • 无足够连续内存空间
  • FD(文件句柄)数量超出限制
  • 线程数量超出限制
  • 虚拟内存不足

activity启动流程

  1. 点击桌面应用图标,Launcher进程将启动Activity(MainActivity)的请求以Binder的方式发送给了AMS。
  2. AMS接收到启动请求后,交付ActivityStarter处理Intent和Flag等信息,然后再交给ActivityStackSupervisior/ActivityStack
    处理Activity进栈相关流程。同时以Socket方式请求Zygote进程fork新进程。
  3. Zygote接收到新进程创建请求后fork出新进程。
  4. 在新进程里创建ActivityThread对象,新创建的进程就是应用的主线程,在主线程里开启Looper消息循环,开始处理创建Activity。
  5. ActivityThread利用ClassLoader去加载Activity、创建Activity实例,并回调Activity的onCreate()方法。这样便完成了Activity的启动。

有现有的IPC方式,为什么重新设计一套Binder机制呢?

主要是出于以上三个方面的考量:

  • 高性能:

    从数据拷贝次数来看Binder只需要进行一次内存拷贝,而管道、消息队列、Socket都需要两次,共享内存不需要拷贝,Binder的性能仅次于共享内存。

  • 稳定性:

    上面说到共享内存的性能优于Binder,那为什么不适用共享内存呢,因为共享内存需要处理并发同步问题,控制负责,容易出现死锁和资源竞争,稳定性较差。而Binder基于C/S架构,客户端与服务端彼此独立,稳定性较好。

  • 安全性:

    我们知道Android为每个应用分配了UID,用来作为鉴别进程的重要标志,Android内部也依赖这个UID进行权限管理,包括6.0以前的固定权限和6.0以后的动态权限,传统IPC只能由用户在数据包里填入UID/PID,这个标记完全
    是在用户空间控制的,没有放在内核空间,因此有被恶意篡改的可能,因此Binder的安全性更高。

PathClassLoader与DexClassLoader有什么区别

  • PathClassLoader:只能加载已经安装到Android系统的APK文件,即/data/app目录,Android默认的类加载器。
  • DexClassLoader:可以加载任意目录下的dex、jar、apk、zip文件。