下面这篇文章汇集了阿里、美团、Oracle等大厂的JVM考点,你是否能回答得上来?
什么是Java虚拟机?为什么Java被称作是“平台无关的编程语言”?
Java代码是怎么运行的?
Java虚拟机是如何加载Java类的?
JVM运行内存的分类
如何监控和诊断JVM堆内和堆外内存使用?
Java四引用是什么?
如何理解JVM内置的编译或GC日志?
JVM的永久代中会发生垃圾回收么?
Java中的两种异常类型是什么?他们有什么区别?
JVM是如何实现同步的?
Java内在模型是什么?
即使编译器有哪些优化?
在什么情况下重复读写操作会被优化?
什么样的垃圾才被回收?
什么时候会导致垃圾回收?
如何利用JFR和JMC监控Java程序?
如何利用UnsafeAPI绕开JVM的控制?
如何利用字节码注入为已有代码加料?
1、什么是Java虚拟机?为什么Java被称作是“平台无关的编程语言”?
Java虚拟机是一个可以执行Java字节码的虚拟机进程。Java源文件被编译成能被Java虚拟机执行的字节码文件。
Java被设计成允许应用程序可以运行在任意的平台,而不需要程序员为每一个平台单独重写或者是重新编译。Java虚拟机让这个变为可能,因为它知道底层硬件平台的指令长度和其他特性。
2、Java代码是怎么运行的?
这个问题可以分三块来回答:
为什么Java要在虚拟机里运行?
Java虚拟机具体是怎样运行Java字节码的?
Java虚拟机的运行效率究竟是怎么样的?
Java之所以要在虚拟机中运行,是因为它提供了可移植性。一旦Java代码被编译为Java字节码,便可以在不同平台上的Java虚拟机实现上运行。此外,虚拟机还提供了一个代码托管的环境,代替我们处理部分冗长而且容易出错的事务,例如内存管理。
Java虚拟机将运行时内存区域划分为五个部分,分别为方法区、堆、PC寄存器、Java方法栈和本地方法栈。Java程序编译而成的class文件,需要先加载至方法区中,方能在Java虚拟机中运行。
为了提高运行效率,标准JDK中的HotSpot虚拟机采用的是一种混合执行的策略。首先,它会解释执行Java字节码,然后会将其中反复执行的热点代码,以方法为单位进行即时编译,翻译成机器码后直接运行在底层硬件之上。HotSpot装载了多个不同的即时编译器,以便在编译时间和生成代码的执行效率之间做取舍。
3、Java虚拟机是如何加载Java类的?
Java虚拟机将字节流转化为Java类的过程,可分为加载、链接以及初始化三大步骤。也可以用盖房子来类比Java虚拟机中的类加载。
加载是指查找字节流,并且据此创建类的过程。以盖房子为例,村里的Tony要盖个房子,那么按照流程他得先找个建筑师,跟他说想要设计一个房型,比如说“一房、一厅、四卫”。这里的房型相当于类,而建筑师,就相当于类加载器。村里有许多建筑师,他们等级森严,但有着共同的祖师爷,叫启动类加载器(bootclassloader)。
加载需要借助类加载器,在Java虚拟机中,类加载器使用了双亲委派模型,即接收到加载请求时,会先将请求转发给父类加载器。
链接,是指将创建成的类合并至Java虚拟机中,使之能够执行的过程。链接还分验证、准备和解析三个阶段。其中,解析阶段为非必须的。
初始化,则是为标记为常量值的字段赋值,以及执行
4、如何监控和诊断JVM堆内和堆外内存使用?
了解JVM内存的方法有很多,具体能力范围也有区别,简单总结如下:
可以使用综合性的图形化工具,如JConsole、VisualVM(注意,从OracleJDK9开始,VisualVM已经不再包含在JDK安装包中)等。这些工具具体使用起来相对比较直观,直接连接到Java进程,然后就可以在图形化界面里掌握内存使用情况。以JConsole为例,其内存页面可以显示常见的堆内存和各种堆外部分使用状态。
也可以使用命令行工具进行运行时查询,如jstat和jmap等工具都提供了一些选项,可以查看堆、方法区等使用数据。
或者,也可以使用jmap等提供的命令,生成堆转储(HeapDump)文件,然后利用jhat或EclipseMAT等堆转储分析工具进行详细分析。
如果你使用的是Tomcat、Weblogic等JavaEE服务器,这些服务器同样提供了内存管理相关的功能。
另外,从某种程度上来说,GC日志等输出,同样包含着丰富的信息。
这里有一个相对特殊的部分,就是是堆外内存中的直接内存,前面的工具基本不适用,可以使用JDK自带的NativeMemoryTracking(NMT)特性,它会从JVM本地内存分配的角度进行解读。
5、JVM的永久代中会发生垃圾回收么?
垃圾回收不会发生在永久代,如果永久代满了或者是超过了临界值,会触发完全垃圾回收(FullGC)。如果你仔细查看垃圾收集器的输出信息,就会发现永久代也是被回收的。这就是为什么正确的永久代大小对避免FullGC是非常重要的原因。
(注:Java8中已经移除了永久代,新加了一个叫做元数据区的native内存区)
6、在Java中,对象什么时候可以被垃圾回收?
当对象对当前使用这个对象的应用程序变得不可触及的时候,这个对象就可以被回收了。
7、Java中的两种异常类型是什么?他们有什么区别?
Java中有两种异常:受检查的(checked)异常和不受检查的(unchecked)异常。不受检查的异常不需要在方法或者是构造函数上声明,就算方法或者是构造函数的执行可能会抛出这样的异常,并且不受检查的异常可以传播到方法或者是构造函数的外面。相反,受检查的异常必须要用throws语句在方法或者是构造函数上声明。还有一些Java异常处理的小建议,我的专栏里都有提到。
8、JVM垃圾回收算法
标记-清除算法:首先标记出所有需要回收的对象,在标记完成后统一回收所有被标记的对象。
复制算法:将可用内存按容量划分为大小相等的两块,每次只使用其中的一块。当一块内存用完了,将还存另外一块上面,然后在把已使用过的内存空间一次清理掉。
标记-整理算法:标记过程与“标记-清除”算法一样,但后续步骤不是直接对可回收对象进行清理,而是让所一端移动,然后直接清理掉端边界以外的内存。
分代收集算法:一般是把Java堆分为新生代和老年代,根据各个年代的特点采用最适当的收集算法。新生代都发现有大批对象死去,选用复制算法。老年代中因为对象存活率高,必须使用“标记-清理”或“标记-整理”算法来进行回收。
以上就是北大青鸟长沙麓谷校区java培训机构小编介绍的“JVM考点:高级Java工程师面试必备”的内容,希望对大家有帮助,如有疑问,请在线咨询,有专业老师随时为你服务。
相关推荐
面试题总结—高级Java工程师面试题
Java高级开发工程师面试题
秋招中高级Java面试题,10道详解,死磕就对了
最新Java工程师面试题整理[社招篇]
大家都在收藏的中级常见Java工程师面试题
腾讯Java高级工程师高频面试题