Android高频面试专题

Stella981
• 阅读 274

点击上方 Android扫地僧 ,选择 星标 公众号

重磅资源、干货分享,快上车!

Android高频面试专题

内存泄漏往往面试会问到是否有解决过实际问题,这个如果答不好,也是很容易露馅的,面试时必须得把这艘火箭造好,才有机会进去拧螺丝。其他完整面试专题,请关注公众号查看。

1、Java虚拟机内存模型

完整内容参考 Java内存模型

Android高频面试专题

虚拟机栈:线程私有,随线程创建而创建。栈里面是一个一个“栈帧”,每个栈帧对应一次方法调用。栈帧中存放了局部变量表(基本数据类型变量和对象引用)、操作数栈、方法出口等信息。当栈调用深度大于JVM所允许的范围,会抛出StackOverflowError的错误。

本地方法栈:线程私有,这部分主要与虚拟机用到的Native方法相关,一般情况下,并不需要关心这部分的内容。

程序计数器:也叫PC寄存器,JVM支持多个线程同时运行,每个线程都有自己的程序计数器。倘若当前执行的是 JVM 的方法,则该寄存器中保存当前执行指令的地址;倘若执行的是native方法,则PC寄存器中为空。(PS:线程执行过程中并不都是一口气执行完,有可能在一个CPU时钟周期内没有执行完,由于时间片用完了,所以不得不暂停执行,当下一次获得CPU资源时,通过程序计数器就知道该从什么地方开始执行)

方法区:方法区存放类的信息(包括类的字节码,类的结构)、常量、静态变量等。字符串常量池就是在方法区中。虽然Java虚拟机规范把方法区描述为堆的一个逻辑部分,但是它却有一个别名叫做Non-Heap(非堆),目的是与Java堆区分开来。很多人都更愿意把方法区称为“永久代”(Permanent Generation)。从jdk1.7已经开始准备“去永久代”的规划,jdk1.7的HotSpot中,已经把原本放在方法区中的静态变量、字符串常量池等移到堆内存中。

:堆中存放的是数组(PS:数组也是对象)和对象。当申请不到空间时会抛出OutOfMemoryError。

2、内存泄漏原理

Android是基于Java的一门语言,其垃圾回收机制也是基于Jvm建立的,所以说Android的GC也是通过可达性分析算法来判定的。但是如果一个存活时间长的对象持有另一个存活时间短的对象就会导致存活时间短的对象在GC时被认定可达而不能被及时回收,而继续停留在堆内存中,也就是我们常说的内存泄漏。Android对每个App内存的使用有着严格的限制,大量的内存泄漏就可能导致OOM(内存溢出),也就是在new对象请求空间时,堆中没有剩余的内存分配所导致的。

3、Java引用类型

Java对引用的分类有 StrongReference(默认引用类型), SoftReference, WeakReference,PhatomReference 四种。

Android高频面试专题

4、OOM是否可以try catch?

只有在一种情况下,这样做是可行的:

在try语句中声明了很大的对象,导致OOM,并且可以确认OOM是由try语句中的对象声明导致的,那么在catch语句中,可以释放掉这些对象,解决OOM的问题,继续执行剩余语句。但是这通常不是合适的做法。

5、finalize()方法

finalize()是Object的protected方法,子类可以覆盖该方法以实现资源清理工作,当对象变成(GC Roots)不可达时,GC会判断该对象是否覆盖了finalize方法,若未覆盖,则直接将其回收。否则,若对象未执行过finalize方法,将其放入F-Queue队列,由一低优先级线程执行该队列中对象的finalize方法。执行finalize方法完毕后,GC会再次判断该对象是否可达,若不可达,则进行回收,否则,对象“复活”。

finalize方法至多由GC执行一次,即使在finalize()方法中复活对象,第二次GC如果对象仍不可达,那么还是会被回收。

6、Android查看内存/CPU占用信息

adb shell dumpsys meminfo pid

adb shell dumpsys cpuinfo|find "包名"

adb shell top

7、Android内存泄漏如何定位

使用Android Studio 自带的AndroidProfiler工具或MAT

使用Square产品的LeakCanary.

详情: https://www.jianshu.com/p/1972a6d1f0fc

8、LeakCanary原理

监测机制利用了Java的WeakReference和ReferenceQueue,通过将Activity(对象)包装到WeakReference中,被WeakReference包装过的Activity对象如果被回收,该WeakReference引用会被放到ReferenceQueue中,通过监测ReferenceQueue里面的内容,就能检查到Activity是否能够被回收。

详细原理:https://blog.csdn.net/tobetheender/article/details/53609563

9、常见内存泄漏的场景

  • 集合类泄漏

    Vector v = new Vector(10);

  • 单例造成的内存泄漏

    由于单例的静态特性使得其生命周期跟应用的生命周期一样长,如果单例内部持有Activity/Fragment/View等的引用,会导致其无法被回收。

  • 匿名内部类/非静态内部类和异步线程

    Java中,非静态内部类和匿名内部类默认会持有外部类的引用,比较容易引起内存泄漏的有Handler, AsyncTask使用匿名内部类形式。

  • 资源未关闭造成的内存泄漏

    对于使用了BraodcastReceiver,ContentObserver,File,游标 Cursor,Stream,Bitmap等资源的使用,应该在Activity销毁时及时关闭或者注销,否则这些资源将不会被回收,造成内存泄漏。

  • 一些不良代码造成的内存压力

    例如,只进行注册而没有反注册,构造 Adapter 时,没有使用缓存的 convertView。

10、避免内存泄漏的优化

直接就是针对上面提到的4点进行优化,集合资源add后不用及时remove;Handler使用静态内部类+弱引用,AsyncTask可以在onDestroy()内调用cancel方法;资源使用完及时进行close获取release;注册与反注册成对出现,Adapter进行convertView复用。

11、一个线程OOM后,其他线程是否还能正常工作?

美团18年三面题目

结合第1题,大家第一反应容易直观觉得是堆溢出,然后结合第1题堆是线程共享的,所以其他线程也都异常。实际上并非如此,当一个线程抛出OOM异常后,它所占据的内存资源会立即全部被释放掉,从而不会影响其他线程的运行。同理,栈溢出也是一样的。如果主线程抛异常退出了,子线程也还能运行,除非这些子线程是守护线程,那么会随着主线程异常结束而结束。


Android高频面试专题

Android高频面试专题

Android高频面试专题

在看点这里

Android高频面试专题

本文分享自微信公众号 - Android扫地僧(Android-Mas)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

点赞
收藏
评论区
推荐文章
blmius blmius
2年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Jacquelyn38 Jacquelyn38
2年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Stella981 Stella981
2年前
Opencv中Mat矩阵相乘——点乘、dot、mul运算详解
Opencv中Mat矩阵相乘——点乘、dot、mul运算详解2016年09月02日00:00:36 \牧野(https://www.oschina.net/action/GoToLink?urlhttps%3A%2F%2Fme.csdn.net%2Fdcrmg) 阅读数:59593
Stella981 Stella981
2年前
KVM调整cpu和内存
一.修改kvm虚拟机的配置1、virsheditcentos7找到“memory”和“vcpu”标签,将<namecentos7</name<uuid2220a6d1a36a4fbb8523e078b3dfe795</uuid
Easter79 Easter79
2年前
Twitter的分布式自增ID算法snowflake (Java版)
概述分布式系统中,有一些需要使用全局唯一ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点,首先他相对比较长,另外UUID一般是无序的。有些时候我们希望能使用一种简单一些的ID,并且希望ID能够按照时间有序生成。而twitter的snowflake解决了这种需求,最初Twitter把存储系统从MySQL迁移
Wesley13 Wesley13
2年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
2年前
Docker 部署SpringBoot项目不香吗?
  公众号改版后文章乱序推荐,希望你可以点击上方“Java进阶架构师”,点击右上角,将我们设为★“星标”!这样才不会错过每日进阶架构文章呀。  !(http://dingyue.ws.126.net/2020/0920/b00fbfc7j00qgy5xy002kd200qo00hsg00it00cj.jpg)  2
Wesley13 Wesley13
2年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
3个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这