JVM内存模型面试题及答案.docxVIP

  1. 1、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。。
  2. 2、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载
  3. 3、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
  4. 4、该文档为VIP文档,如果想要下载,成为VIP会员后,下载免费。
  5. 5、成为VIP后,下载本文档将扣除1次下载权益。下载后,不支持退款、换文档。如有疑问请联系我们
  6. 6、成为VIP后,您将拥有八大权益,权益包括:VIP文档下载权益、阅读免打扰、文档格式转换、高级专利检索、专属身份标志、高级客服、多端互通、版权登记。
  7. 7、VIP文档为合作方或网友上传,每下载1次, 网站将根据用户上传文档的质量评分、类型等,对文档贡献者给予高额补贴、流量扶持。如果你也想贡献VIP文档。上传文档
查看更多

JVM内存模型面试题及答案

1.面试官:能说说你理解的JVM内存模型吗?它和Java内存模型(JMM)是一回事吗?

答案:

JVM内存模型其实是JVM对内存的划分规则,简单说就是把JVM管理的内存拆成几个功能不同的区域,比如我们常说的堆、虚拟机栈、方法区这些,每个区域有自己的用途、创建销毁时机,还会对应不同的OOM场景。

它和JMM完全不是一回事——JMM是“Java内存模型”,关注的是多线程下变量的可见性、原子性、有序性,比如volatile怎么保证可见性、synchronized怎么解决原子性问题,本质是一套“线程安全的规则约定”;而JVM内存模型是“物理内存区域划分”,是JVM运行时的内存结构,两者一个管“线程安全规则”,一个管“内存区域分配”,别搞混了。

2.面试官:JVM里哪些内存区域是线程私有的?为什么要设计成私有?

答案:

线程私有的区域有三个:程序计数器、虚拟机栈、本地方法栈。

设计成私有的核心原因是“和线程生命周期绑定,避免线程间干扰”:

程序计数器:记录当前线程执行的字节码行号(比如分支、循环跳转要靠它定位),线程切换后得恢复自己的执行位置,私有才能保证每个线程的执行流程不混乱;

虚拟机栈:每个方法执行时会创建一个栈帧(存局部变量、操作数栈这些),方法调用完栈帧就出栈,线程结束栈就销毁,私有能避免不同线程的栈帧互相覆盖;

本地方法栈:和虚拟机栈类似,只是给native方法(比如调用C++写的方法)用的,逻辑一样,私有才能保证native方法执行时的内存安全。

像堆、方法区就是线程共享的,所以多线程操作堆里的对象才会有线程安全问题。

3.面试官:堆内存为什么要分代?年轻代、老年代、Survivor区各自的作用是什么?

答案:

堆分代的核心思路是“根据对象的生命周期不同,用不同的GC策略,提高回收效率”——因为实际开发中,大多数对象都是“朝生夕死”的(比如方法里的局部变量,方法执行完就没用了),如果不分代,每次GC都要扫描整个堆,效率太低。

具体作用:

年轻代:存刚创建的对象,默认占堆的1/3,又分Eden区和两个Survivor区(S0、S1,默认比例8:1:1)。新对象先放Eden,Eden满了触发MinorGC(轻量GC),活下来的对象移到S0;下次Eden满了再GC,活下来的对象(包括S0里的)移到S1,同时年龄+1;每次GC后S0和S1会交换角色,保证总有一个空的。

老年代:存“活的久”的对象(默认年龄到15就移过来,可通过参数调整),占堆的2/3。老年代里的对象存活时间长,所以GC频率低,一般触发MajorGC(或FullGC)才会回收,FullGC会同时回收年轻代和老年代,耗时比MinorGC久很多。

Survivor区:核心是“过滤短期对象,避免年轻代的活对象频繁进入老年代”——如果没有Survivor,Eden里活下来的对象直接进老年代,老年代很快就满了,会频繁触发FullGC,影响性能。

4.面试官:实际开发中遇到过OOM吗?哪些内存区域会导致OOM?举个你遇到的例子

答案:

遇到过,比如堆OOM、元空间OOM、虚拟机栈OOM,这三种比较常见:

堆OOM:之前做一个数据导入功能,把数据库里的10万条数据全查出来存到ArrayList里,没分页,运行一会儿就报“java.lang.OutOfMemoryError:Javaheapspace”。原因是堆里创建的对象太多(10万条数据的对象),超过了堆的最大内存(-Xmx设置的2G),GC也回收不掉(因为ArrayList还持有引用),就溢出了。后来改成分页查询,每次查1000条,处理完就释放引用,就好了。

元空间OOM:之前用SpringBoot开发时,不小心写了个循环创建动态代理类的代码(比如用CGLIB循环生成代理类),运行一会儿报“java.lang.OutOfMemoryError:Metaspace”。因为元空间是存类信息的(类结构、方法表这些),动态代理会不断生成新的类,元空间默认是用本地内存,虽然理论上可以扩,但当时没配置参数,类太多就满了。后来改了代码,避免循环生成代理类,再加上“-XX:MetaspaceSize=128m-XX:MaxMetaspaceSize=256m”限制大小,就解决了。

虚拟机栈OOM:之前写递归方法时没加终止条件(比如求斐波那契数列,递归深度没控制),报“java.lang.StackOverflowError”(其实也算栈溢出的一种O

文档评论(0)

151****9429 + 关注
实名认证
文档贡献者

该用户很懒,什么也没介绍

1亿VIP精品文档

相关文档