Android面试(JVM部分,含存储区、GC、内存溢出泄漏优化)

先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前阿里P7

深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
img
img
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以添加V获取:vip204888 (备注Android)
img

正文

存放常量,对于相等的字符串,常量池中只有一份,由系统释放

程序代码区


存放函数体的二进制代码非arm(随机访问存储器)存储如硬盘等永久存储空间

2、GC机制

================

(1)如何确定哪些对象可以回收?(可达性分析算法)


引用计数法:判断对象的引用数量。实现方法:给对象添加引用计数器,当有引用时就+1,引用完成并失效时就-1,当计数器的值为0时,则被视为失效的垃圾对象,则可以被回收。但是这个方法不能解决循环引用问题,如对象a,b互相引用,则gc机制无法识别,所以没有采用这个机制。

可达性分析算法:通过判断对象的引用链是否可达来决定对象是否可以被回收。实现方法:把所有的引用关系看作一张图,通过一系列的名为GCRoot的根节点作为起始点开始往下搜索,走过的路就叫引用链,当一个对象没有任何引用链连接GcRoot时,则认为不可达,则可以回收

(2)jvm会在什么时候回收?


CPU空闲时回收;堆内存满了时回收;主动调用System.gc()时回收。

当新生代内存不够用时为Minor GC,当JVM内存不够用时为Full GC。

(3)gc怎么回收?使用最多的是分代收集算法


标记-清除算法:最基础的算法,先标记,回收时将带有标记的内存都回收。虽然简单,但标记和清除的效率都很低,并且清除内存后会造成内存碎片化,当需要保存较大对象时无法找到足够的连续内存来保存,造成空间浪费。

复制算法:为了解决内存碎片化问题,将内存分为大小相等的两块AB,每次只使用一块内存,如这次使用A块,当垃圾回收时,就将A上还活跃的对象复制到B内存中,然后一次性清理掉A中的内存空间。这样不会有内存碎片化问题,但总是复制,效率变低,关键是内存还少了一半儿。所以将该算法进行了改进,内存区域不再划分为大小相等的两块,而是以8:1:1的比例分为Eden区,和两个Survivor区,每次都会优先使用Eden区,当Eden区满了,就将活跃对象复制到survivor区,若此时存活的对象太多导致survivor区不够时,就会通过分配担保机制将对象复制到老年代中。

标记-整理算法:和标记-清除算法类似,内存回收后,将存活的对象向左移动,整理到一起,避免产生碎片化。

分代收集算法:jvm使用最多的算法,根据对象的生命周期,将堆分为新生代和老年代。在新生代中,由于对象生存期短,每次回收都会有大量对象死去,所以采用复制算法。老年代里对象存活率高,所以采用标记-整理算法或者标记-清除算法。

3、内存分配

==========

3.1,jvm内存有3个区域:


新生代:一般都是新生成的对象,目标是尽可能快速的回收那些生命周期短的对象,对象从这个区域被回收的过程为Minor GC,因为每次回收都有大量对象被回收,少量存货,所以使用的是复制算法。空间分配为一个伊甸园空间Eden,两个幸存者空间SurvivorA,B,每次垃圾回收时,Eden里存活的对象复制到幸存者A中,然后清空Eden,当A满了,就将A中存活的复制到B,清空A,然后AB互换身份继续循环下去。当循环n次(一般是15次)后,依然存活的被转到老年代。

老年代:一般是生命周期较长的对象。空间比新生代大,GC次数比新生代少,老年代满了时会回收,回收时间长,回收过程为Major GC或Full GC,因为对象存活率高,所以使用的是标记-整理算法

永久代:存放静态文件,如Java类常量,字符串常量等,回收过程为Major GC,只有所有实例被回收,ClassLoader被回收,Class对象无法通过任何途径访问包括反射时,才会发生回收机制。

3.2,内存分配


== :对基本数据类型比较的是值,对引用数据类型比较的是地址。

equals:只能比较引用数据类型,基本数据类型没有此方法,如果没有重写Object的equals方法,则该方法返回的结果就是==的结果,重写后的equals方法比较的是对象中的属性,如String类就重写了equals方法,比较的是对象的值。

String s1 = new String(“helloworld”);//创建了两个对象,“”引起来的在常量池中,new出的对象在堆中。

c,c1,c2的地址值相同,都在常量池中,所以返回true。d相当于d=new String(a+b),是在堆内存中,地址不同所以返回false。

4、内存泄漏及解决方法

==================

指程序中动态分配内存给一些临时对象,对象可达无法被GC回收,但对象已无用。

4.1场景:

长生命周期的对象持有短生命周期对象的引用,如全局静态map中缓存局部变量,但没有做清空操作,map会越来越大,造成内存泄漏;

非静态内部类持有外部类的引用:如使用Handler时,当activity被销毁了,handler发送的message没有执行完毕,那么handler就不会被回收。但是由于非静态内部类默认持有外部类的引用,又因为handler可达,并持有activity引用,所以jvm会错误的认为activity可达而不执行GC,这时activity就造成内存泄漏。

4.2解决方法

尽在释放无用对象的引用;

5、内存溢出

==========

内存泄漏时内存溢出的主要原因,但不是唯一原因。

堆内存溢出:新生代中survivor和老年代仍然无法存放Eden复制过来的对象,导致无法在Eden中new对象。

方法区(全局区)内存溢出:加载的类过多,或者使用反射等生成的动态代理类过多时。

线程栈溢出:每个线程都独有一块内存结构,当递归太深或者调用层级过多时会导致溢出。

解决方法:加大JVM内存大小;减少String的使用,可以用StringBuffer,StringBuilder替代;尽量少用静态变量,因为静态变量放在全局区(方法区,永久代),基本不会GC;避免在循环中创建对象;不要一次性加载过多数据,如数据库取数据;内存泄漏的解决方法都加上;

6、WebView内存泄露

=================

(1)通过布局的viewgroup,使用viewgroup.add方式添加webview,销毁的时候先通过viewgroup.removeView(webview)删除webview,然后webview.destroy;另外传入webview的Context采用弱引用的方式

(2)新开进程,关闭页面将进程关闭

7、类加载

=====

7.1、7个过程


主要就是加载、验证、准备、解析、初始化、使用、卸载。简单说就是虚拟机把描述类的数据从Class文件加载到内存,并对数据进行验证、解析和初始化,最终形成可以被虚拟机直接使用的Java类型。

7.1加载:加载是类加载的第一个过程,在这个过程,将完成以下3件事:

(1)通过一个类的全限定名获取该类的二进制流。

(2)将该二进制流中的静态存储结构转化为方法去运行时数据结构。

(3)在内存中生成该类的Class对象,作为该类的数据访问入口。

7.2验证:目的是为了确保Class文件的字节流中的信息不会危害到虚拟机,在该阶段主要完成以下4中验证:

(1)文件格式验证:验证字节流是否符合Class文件的规范,如主次版本号是否在当前虚拟机范围内,常量池中的常量是否有不被支持的类型。

(2)元数据验证:对字节码描述的信息进行语义分析,如这个类是否有父类,是否继承了不能被继承的类等。

(3)字节码验证:这是验证过程最复杂的阶段,通过验证数据流和控制流的分析,确定程序语义是否正确,主要针对方法体的验证。如:方法中的类型转换是否正确,跳转指令是否正确等。

(4)符号引用验证:这个动作在后面的解析过程中发生,主要是为了确保解析工作能正确执行。

7.3准备:为类的静态变量分配内存并将其初始化为默认值,这些内存都在静态区进行分配。此阶段不分配类中的实例变量的内存,实例变量将会在对象实例化时随着对象一起分配在Java堆中。

public static int num = 2;//在准备阶段num为0,初始化阶段才会为2.

7.4解析:主要完成符号引用到直接引用的转换动作,解析动作并不一定在初始化完成之前,也有可能是之后。

7.5初始化:是类加载的最后一步,前面的类加载过程,除了在加载阶段用户应用程序可以通过自定义类加载器参与之外,其余阶段完全由虚拟机主导和控制。到了初始化阶段,在真正开始执行类中定义的Java程序代码。

最后

答应大伙的备战金三银四,大厂面试真题来啦!

这份资料我从春招开始,就会将各博客、论坛。网站上等优质的Android开发中高级面试题收集起来,然后全网寻找最优的解答方案。每一道面试题都是百分百的大厂面经真题+最优解答。包知识脉络 + 诸多细节。
节省大家在网上搜索资料的时间来学习,也可以分享给身边好友一起学习。

《960全网最全Android开发笔记》

《379页Android开发面试宝典》

包含了腾讯、百度、小米、阿里、乐视、美团、58、猎豹、360、新浪、搜狐等一线互联网公司面试被问到的题目。熟悉本文中列出的知识点会大大增加通过前两轮技术面试的几率。

如何使用它?
1.可以通过目录索引直接翻看需要的知识点,查漏补缺。
2.五角星数表示面试问到的频率,代表重要推荐指数

《507页Android开发相关源码解析》

只要是程序员,不管是Java还是Android,如果不去阅读源码,只看API文档,那就只是停留于皮毛,这对我们知识体系的建立和完备以及实战技术的提升都是不利的。

真正最能锻炼能力的便是直接去阅读源码,不仅限于阅读各大系统源码,还包括各种优秀的开源库。

腾讯、字节跳动、阿里、百度等BAT大厂 2020-2021面试真题解析

资料收集不易,如果大家喜欢这篇文章,或者对你有帮助不妨多多点赞转发关注哦。文章会持续更新的。绝对干货!!!

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加V获取:vip204888 (备注Android)
img

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

4003345)]

资料收集不易,如果大家喜欢这篇文章,或者对你有帮助不妨多多点赞转发关注哦。文章会持续更新的。绝对干货!!!

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加V获取:vip204888 (备注Android)
[外链图片转存中…(img-SxOycqSY-1713464003345)]

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 14
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值