您的当前位置:首页正文

《变态面试官》系列——JVM基础你会么

2024-11-29 来源:个人技术集锦

锲子

一入编程深似海,编程世界Very深。

这里是九神说编程,今天给大家说的是一个顶级大佬闲的无聊,在编程世界已经999级,闲来无事去新手村练小号的故事。

大佬本以为只要拿出0.001%的功力就可以轻松入职升级了,没有想到却遇上了变态面试官!

“看来,我需要使出我1%的功力了!”,大佬明悟道。

介绍一下作者本人,我虽名为九神,但在那场大战中连观战的资格都没有,以下的一切都是大佬小号口传于我的。而我,只是以第一人称口述,记录下了那场对决的万分之一!本次是第二面现场!

面试开始

虽然上次我在基础面试中回答了

UTF-16是怎么实现Unicode编码的,以及UTF-8、UTF-16和UTF-32的选型

这种最最最基础的Java问题,但是我没有获得工作机会,此番升到2级之后,我获得了2面的机会。我要拿下offer!打怪升级!

他来了他来了,那个头发浓密,全身西服笔挺的30岁大叔面试官向我走来了!看着对方这张好像在我长远记忆中见过的帅气脸庞,我实在想不起来他是谁!

面试官笑呵呵的说道:“小伙子不错,居然升到了2级,我们还是先来几个简单的题目热热身吧!

1、先说个十种JDK中自带的JVM相关工具吧!

果然是简单的热身题目,但是我依然认真的回答道:大叔你好!,比较常见的有如下几种:

  • jstack:java虚拟机自带的一种堆栈跟踪工具。
  • jstat:用于监控基于HotSpot的JVM,对其堆的使用情况进行实时的命令行的统计。
  • jmap:输出所有内存中对象的工具,可以将VM 中的heap,以二进制输出成文本。
  • jinfo:用于打印指定Java进程、核心文件或远程调试服务器的Java配置信息。配置信息包括Java系统属性、Java虚拟机命令行标识参数。
  • jconsole:一个java GUI监视工具,可以以图表化的形式显示各种数据。并可通过远程连接监视远程的服务器VM。
  • jvisualvm:提供了一个可视界面,用于查看 Java 虚拟机上运行的基于 Java 技术的应用程序的详细信息。启动起来后和jconsole 一样同样可以选择本地和远程。
  • jhat:是用来分析Java堆的命令,可以将堆中的对象以html的形式显示出来,包括对象的数量,大小等等,并支持对象查询语言。
  • jdb:用来对core文件和正在运行的Java进程进行实时地调试,里面包含了丰富的命令帮助您进行调试,它的功能和Sun studio里面所带的dbx非常相似,但 jdb是专门用来针对Java应用程序的。
  • jstatd:是一个基于RMI的服务程序,它用于监控基于HotSpot的JVM中资源的创建及销毁,并且提供了一个远程接口允许远程的监控工具连接到本地的JVM执行命令。
  • jcmd:它是一个多功能工具,可以用来导出堆,查看Java进程,导出线程信息,执行GC等。
  • NMT:JDK提供的一个Native Memory Tracking工具,跟踪JVM内部的内存使用。

你让我答10个,那还不答上11个?肯定有加分啊!

2、如何通过 Java 程序来判断 JVM 是 32 位 还是 64位?

可以通过System.getProperty(“sun.arch.data.model”)或者System.getProperty(“os.arch”)这两种办法在Java程序里获取JVM所运行的操作系统的是32位的还是64位。

3、说上5个JVM的种类吧

HotSpot VM、J9 VM、Sun Classic VM、Exact VM、JRockit VM、Dalvik VM、Microsoft JVM、Azul VM、Liquid VM、Zing VM先说这些吧!

其中我们最主流用的是HotSpot VM,可以通过java -version查看你自己用的VM种类。

问常识的时候,可以多回答一点,代表我不是小白!

4、32位的JVM和64位的JVM最大堆内存是多少?

32 位的 JVM理论上堆内存可以到达 2^32, 即 4GB,但实际上会比这个小很多。

以Hotspot VM为例,在Windows下,最大的堆内存大约在1.5G左右;在基于较新的linux kernel的Linux系统下,其限制在2.5到3G之间,在早前的linux kernel下,大约在2G左右;在Solaris下,为3.3G左右。

64 位 JVM 允许指定最大的堆内存,理论上可以达到 2^64,这是一个非常大的数字,实际上你可以指定堆内存大小到 100GB。甚至有的 JVM,如 Azul,堆内存到 1000G 都是可能的。

5、讲讲看JVM的主要组成部分和他们的作用。
  • 类加载器(ClassLoader)
  • 运行时数据区(Runtime Data Area)
  • 执行引擎(Execution Engine)
  • 本地库接口(Native Interface)

他们的作用是,首先通过类加载器(ClassLoader)会把 Java 代码转换成字节码,运行时数据区(Runtime Data Area)再把字节码加载到内存中。

而字节码文件只是 JVM 的一套指令集规范,并不能直接交个底层操作系统去执行,因此需要特定的命令解析器执行引擎(Execution Engine),将字节码翻译成底层系统指令,再交由 CPU 去执行,

而这个过程中需要调用其他语言的本地库接口(Native Interface)来实现整个程序的功能。

如果这个不懂,赶紧看下面的图,这个是真的很基本要会的!这里面有些题是专家级别的,但是这个是P5就要会的!

6、具体说说类加载器是干嘛的?类加载有哪几种?

类加载器负责加载所有的类,其为所有被载入内存中的类生成一个java.lang.Class实例对象。

一旦一个类被加载入JVM中,同一个类就不会被再次载入了。正如一个对象有一个唯一的标识一样,一个载入JVM的类也有一个唯一的标识。

在Java中,一个类用其全限定类名(包括包名和类名)作为标识;但在JVM中,一个类用其全限定类名和其类加载器作为其唯一标识。

例如,如果在pg的包中有一个名为Student的类,被类加载器ClassLoader的实例ns负责加载,则该Student类对应的Class对象在JVM中表示为(Student.pg.ns)。

这意味着两个类加载器加载的同名类:(Student.pg.ns)和(Student.pg.ns2)是不同的、它们所加载的类也是完全不同、互不兼容的。

类加载器分为三类:

  • 启动类加载器(Bootstrap ClassLoader),是虚拟机自身的一部分,用来加载JAVA_HOME/lib/目录中的,或者被 -Xbootclasspath 参数所指定的路径中并且被虚拟机识别的类库;
  • 扩展类加载器(Extension ClassLoader):负责加载\lib\ext目录或Java. ext. dirs系统变量指定的路径中的所有类库;
  • 应用程序类加载器(Application ClassLoader)。负责加载用户类路径(classpath)上的指定类库,我们可以直接使用这个类加载器。一般情况,如果我们没有自定义类加载器默认就是用这个加载器。
7、类加载的执行过程是什么样的?

从类的生命周期而言,一般是加载、验证、准备、解析、初始化、使用和卸载这7个过程。

其中,加载、验证、准备、初始化和卸载这5个阶段的顺序是确定的,类的加载过程必须按照这种顺序进行,

而解析阶段则不一定,它在某些情况下可能在初始化阶段后在开始,因为java支持运行时绑定。

一定要回答全面,很多人回答5个其实不会得到满分,而且必须理解每个名词是干嘛的

8、JVM加载类有哪些机制?

JVM的类加载机制主要有如下3种:

**全盘负责:**所谓全盘负责,就是当一个类加载器负责加载某个Class时,该Class所依赖和引用其他Class也将由该类加载器负责载入,除非显示使用另外一个类加载器来载入。

**双亲委派:**所谓的双亲委派,则是先让父类加载器试图加载该Class,只有在父类加载器无法加载该类时才尝试从自己的类路径中加载该类。

通俗的讲,就是某个特定的类加载器在接到加载类的请求时,首先将加载任务委托给父加载器,依次递归,

如果父加载器可以完成类加载任务,就成功返回;只有父加载器无法完成此加载任务时,才自己去加载。

**缓存机制:**缓存机制将会保证所有加载过的Class都会被缓存,当程序中需要使用某个Class时,类加载器先从缓存区中搜寻该Class。

只有当缓存区中不存在该Class对象时,系统才会读取该类对应的二进制数据,并将其转换成Class对象,存入缓冲区中。

这就是为很么修改了Class后,必须重新启动JVM,程序所做的修改才会生效的原因。

9、小伙子基础还可以么,那讲讲看HotSpot VM中的JIT是做什么的。

Java程序最初是通过解释器(Interpreter)进行解释执行的,当虚拟机发现某个方法或代码块的运行特别频繁时,就会把这些代码认定为“热点代码”。

为了提高热点代码的执行效率,在运行时,虚拟机将会把这些代码编译成与本地平台相关的机器码,并进行各种层次的优化,完成这个任务的编译器称为即时编译器,英文名是Just In Time Compiler,也就是JIT。

而这种采用解释执行 + JIT(just-in-time 即时) 编译器编译热点的方式,就是HotSpot名字的来由。

就是要秀别人不知道的历史题,哈哈哈,就是要骚要秀,果然不愧是999级的小号

10、那你说说JIT有哪些编译器,这些编译器在何种情况下使用?

JIT有两种编译器:Client Compiler和Server Compiler。

其中Client Compiler,我们通常称为C1,这是一种轻量级编译器,特点是启动速度快,使用的场景是相比程序稳定时的运行速度,我们更在意内存占用空间要小。

而Server Compiler,我们通常称为C2,这是一种重量级编译器,使用的场景是相比内存占用空间,我们更在意程序稳定时的运行速度。

我们可以通过-client来使用Client Compiler,通过-server来使用Server Compiler。

在JDK7之后,我们就可以通过TieredCompilation这一分层编译模式,同时使用两种编译器,先使用C1达到启动时间短,而运行一段时间后,又唤起C2达到程序运行速度快的效果。

因为高P一般不写博客,所以这里国内的文章好像没有对的,经常面试很多人这里理解的一塌糊涂。尤其是那些认为Client的适用场景是客户端,Server是服务端的,这个理解不对,因为桌面应用未必轻量,比如视频类桌面应用。这里就能反映很多人不会看oracle的官方文档。

11、JIT运行中的罕见陷阱是什么?

罕见陷阱是JIT这种典型的PGO(profile guide optimization)所带来的问题。

当JIT判断一段代码是热点代码后,但是下一次的行为和之前完全不同,这时候被已经编译的这个热点代码就完全无效了,这种行为就叫罕见陷阱。

当产生罕见陷阱之后,native code就会回滚(deoptimization)到解释器(interpreter),然后再次采集数据进行下一次优化。

面试结束

面试官大叔看了一眼手腕上的百达翡丽,说时间不早了,要不先这样吧,让我回去等下次面试的通知。

我问道:那什么时候下次面试呢?

“等你升到3级的时候吧!下次还是JVM,这次过于简单了!”,面试官留下这就话就走了。

看不起小号么?还需要透漏下次还是JVM?来吧!大不了我给你写个比Hotspot还好的!(不,我不能透漏自己是999级小号的秘密!)

后续

那大佬如何才能升级呢?据大佬透漏,需要有人给他的口述点赞达到一定数量方可升级,只有升级到3级,才能进入第三面!

这就是有幸聆听大佬口述,我来执笔写下这篇文章的缘由!

还不给点赞么?没下一篇了啊!

点关注,不迷路

好了各位,以上就是这篇文章的全部内容了,能看到这里的人呀,都是能进大厂的高端人才

我后面会每周都更新几篇一线互联网大厂面试和常用技术栈相关的文章,非常感谢高端人才们能看到这里,如果这个文章写得还不错,觉得「九神说编程」有点东西的话 求点赞? 求关注❤️ 求分享?九神来说真的 非常有用!!!

注意:博文会比公号晚一周哦!

白嫖不好,创作不易, 各位的支持和认可,就是我创作的最大动力,我们下篇文章见!

其他

给大家放个我做的长图,哈哈哈

显示全文