Android面试(JVM部分,含存储区、GC(1),Android插件化入门指南

(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程序代码。

7.2、类加载器双亲委派模型机制


当一个类收到了类加载请求时,不会自己先去加载这个类,而是将其委派给父类,由父类去加载,如果此时父类不能加载,反馈给子类,则由子类去完成类的加载。

7.3、类加载器的定义和种类


定义:实现通过类的权限定名获取该类的二进制字节流的代码块叫做类加载器。

种类:

(1)启动类加载器:用来加载Java核心类库,无法被Java程序直接引用。

(2)扩展类加载器:加载Java的扩展库,Java虚拟机的实现会提供一个扩展库目录,该类加载器在此目录里查找并加载Java类。

(3)系统类加载器:根据Java应用的类路径来加载Java类,一般来说,Java应用的类都是由他加载的,可以通过ClassLoader.getSystemClassLoader()来获取它 。

(4)用户自定义的类加载器:继承java.lang.ClassLoader类的方式实现。

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

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

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

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

如果你觉得这些内容对你有帮助,可以添加V获取:vip204888 (备注Android)
img

尾声

最后,我再重复一次,如果你想成为一个优秀的 Android 开发人员,请集中精力,对基础和重要的事情做深度研究。

对于很多初中级Android工程师而言,想要提升技能,往往是自己摸索成长,不成体系的学习效果低效漫长且无助。 整理的这些架构技术希望对Android开发的朋友们有所参考以及少走弯路,本文的重点是你有没有收获与成长,其余的都不重要,希望读者们能谨记这一点。

最后想要拿高薪实现技术提升薪水得到质的飞跃。最快捷的方式,就是有人可以带着你一起分析,这样学习起来最为高效,所以为了大家能够顺利进阶中高级、架构师,我特地为大家准备了一套高手学习的源码和框架视频等精品Android架构师教程,保证你学了以后保证薪资上升一个台阶。

当你有了学习线路,学习哪些内容,也知道以后的路怎么走了,理论看多了总要实践的。

进阶学习视频

附上:我们之前因为秋招收集的二十套一二线互联网公司Android面试真题 (含BAT、小米、华为、美团、滴滴)和我自己整理Android复习笔记(包含Android基础知识点、Android扩展知识点、Android源码解析、设计模式汇总、Gradle知识点、常见算法题汇总。)

本文已被CODING开源项目:《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》收录

一个人可以走的很快,但一群人才能走的更远。如果你从事以下工作或对以下感兴趣,欢迎戳这里加入程序员的圈子,让我们一起学习成长!

AI人工智能、Android移动开发、AIGC大模型、C C#、Go语言、Java、Linux运维、云计算、MySQL、PMP、网络安全、Python爬虫、UE5、UI设计、Unity3D、Web前端开发、产品经理、车载开发、大数据、鸿蒙、计算机网络、嵌入式物联网、软件测试、数据结构与算法、音视频开发、Flutter、IOS开发、PHP开发、.NET、安卓逆向、云计算

很快,但一群人才能走的更远。如果你从事以下工作或对以下感兴趣,欢迎戳这里加入程序员的圈子,让我们一起学习成长!**](https://bbs.csdn.net/forums/4304bb5a486d4c3ab8389e65ecb71ac0)

AI人工智能、Android移动开发、AIGC大模型、C C#、Go语言、Java、Linux运维、云计算、MySQL、PMP、网络安全、Python爬虫、UE5、UI设计、Unity3D、Web前端开发、产品经理、车载开发、大数据、鸿蒙、计算机网络、嵌入式物联网、软件测试、数据结构与算法、音视频开发、Flutter、IOS开发、PHP开发、.NET、安卓逆向、云计算

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值