

面试官:Java从编译到执行,发生了什么?
source link: https://zhuanlan.zhihu.com/p/422611640
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

面试官:Java从编译到执行,发生了什么?
面试官:今天从基础先问起吧,你是怎么理解Java是一门「跨平台」的语言,也就是「一次编译,到处运行的」?
候选者:很好理解啊,因为我们有JVM。
候选者:Java源代码会被编译为class文件,class文件是运行在JVM之上的。
候选者:当我们日常开发安装JDK的时候,可以发现JDK是分「不同的操作系统」,JDK里是包含JVM的,所以Java依赖着JVM实现了『跨平台』
候选者:JVM是面向操作系统的,它负责把Class字节码解释成系统所能识别的指令并执行,同时也负责程序运行时内存的管理。

面试官:那要不你来聊聊从源码文件(.java)到代码执行的过程呗?
候选者:嗯,没问题的
候选者:简单总结的话,我认为就4个步骤:编译->加载->解释->执行
候选者:编译:将源码文件编译成JVM可以解释的class文件。
候选者:编译过程会对源代码程序做 「语法分析」「语义分析」「注解处理」等等处理,最后才生成字节码文件。
候选者:比如对泛型的擦除和我们经常用的Lombok就是在编译阶段干的。
候选者:加载:将编译后的class文件加载到JVM中。
候选者:在加载阶段又可以细化几个步骤:装载->连接->初始化
候选者:下面我对这些步骤又细说下哈。
候选者:【装载时机】为了节省内存的开销,并不会一次性把所有的类都装载至JVM,而是等到「有需要」的时候才进行装载(比如new和反射等等)
候选者:【装载发生】class文件是通过「类加载器」装载到jvm中的,为了防止内存中出现多份同样的字节码,使用了双亲委派机制(它不会自己去尝试加载这个类,而是把请求委托给父加载器去完成,依次向上)
候选者:【装载规则】JDK 中的本地方法类一般由根加载器(Bootstrp loader)装载,JDK 中内部实现的扩展类一般由扩展加载器(ExtClassLoader )实现装载,而程序中的类文件则由系统加载器(AppClassLoader )实现装载。
候选者:装载这个阶段它做的事情可以总结为:查找并加载类的二进制数据,在JVM「堆」中创建一个java.lang.Class类的对象,并将类相关的信息存储在JVM「方法区」中
面试官:嗯…
候选者:通过「装载」这个步骤后,现在已经把class文件装载到JVM中了,并创建出对应的Class对象以及类信息存储至方法区了。
候选者:「连接」这个阶段它做的事情可以总结为:对class的信息进行验证、为「类变量」分配内存空间并对其赋默认值。
候选者:连接又可以细化为几个步骤:验证->准备->解析
候选者:1. 验证:验证类是否符合 Java 规范和 JVM 规范
候选者:2. 准备:为类的静态变量分配内存,初始化为系统的初始值
候选者:3. 解析:将符号引用转为直接引用的过程
面试官:嗯…
候选者:通过「连接」这个步骤后,现在已经对class信息做校验并分配了内存空间和默认值了。
候选者:接下来就是「初始化」阶段了,这个阶段可以总结为:为类的静态变量赋予正确的初始值。
候选者:过程大概就是收集class的静态变量、静态代码块、静态方法至()方法,随后从上往下开始执行。
候选者:如果「实例化对象」则会调用方法对实例变量进行初始化,并执行对应的构造方法内的代码。
候选者:扯了这么多,现在其实才完成至(编译->加载->解释->执行)中的加载阶段,下面就来说下【解释阶段】做了什么
候选者:初始化完成之后,当我们尝试执行一个类的方法时,会找到对应方法的字节码的信息,然后解释器会把字节码信息解释成系统能识别的指令码。
候选者:「解释」这个阶段它做的事情可以总结为:把字节码转换为操作系统识别的指令
候选者:在解释阶段会有两种方式把字节码信息解释成机器指令码,一个是字节码解释器、一个是即时编译器(JIT)。
候选者:JVM会对「热点代码」做编译,非热点代码直接进行解释。当JVM发现某个方法或代码块的运行特别频繁的时候,就有可能把这部分代码认定为「热点代码」
候选者:使用「热点探测」来检测是否为热点代码。「热点探测」一般有两种方式,计数器和抽样。HotSpot使用的是「计数器」的方式进行探测,为每个方法准备了两类计数器:方法调用计数器和回边计数器
候选者:这两个计数器都有一个确定的阈值,当计数器超过阈值溢出了,就会触发JIT编译。
候选者:即时编译器把热点方法的指令码保存起来,下次执行的时候就无需重复的进行解释,直接执行缓存的机器语言
面试官:嗯…
候选者:解释阶段结束后,最后就到了执行阶段。
候选者:「执行」这个阶段它做的事情可以总结为:操作系统把解释器解析出来的指令码,调用系统的硬件执行最终的程序指令。
候选者:上面就是我对从源码文件(.java)到代码执行的过程的理解了。
面试官:嗯…我还想问下你刚才提到的双亲委派模型…
候选者:下次一定!
本文总结:
- Java跨平台因为有JVM屏蔽了底层操作系统
- Java源码到执行的过程,从JVM的角度看可以总结为四个步骤:编译->加载->解释->执行
- 「编译」经过 语法分析、语义分析、注解处理 最后才生成会class文件
- 「加载」又可以细分步骤为:装载->连接->初始化。装载则把class文件装载至JVM,连接则校验class信息、分配内存空间及赋默认值,初始化则为变量赋值为正确的初始值。连接里又可以细化为:验证、准备、解析
- 「解释」则是把字节码转换成操作系统可识别的执行指令,在JVM中会有字节码解释器和即时编译器。在解释时会对代码进行分析,查看是否为「热点代码」,如果为「热点代码」则触发JIT编译,下次执行时就无需重复进行解释,提高解释速度
- 「执行」调用系统的硬件执行最终的程序指令
我最近一直在连载《对线面试官》系列,目前已经连载38篇啦!一个说人话的面试系列!
【大厂面试知识点】、【简历模板】、【原创文章】电子书,共有1263页
我把这些上传到网盘,你们有需要直接下载就好了。做到这份上了,不会还想白嫖吧?点赞和转发又不用钱。
链接:pan.baidu.com/s/1pQTuKBYs… 密码:3wom
收藏等于白嫖,点赞才是真情!
Recommend
-
42
在一个 Linux 内核 4.18-rc1 的 Pull Request 中,开发者 Andy Shevchenko 表示其在对设备属性框架进行更新时,移除了 union 别名,这引发了 Linus 的暴怒。 这一次 Linus Torvalds 发怒的原因在于 Andy 给出...
-
54
当我们在写代码时,一个方法内部的行数自然是越少越好,这样逻辑清晰、方便阅读,其实好处远不止如此,通过即时编译,甚至可以提高执行时的性能,今天就让我们好好来了解一下其中的原理。 简介 当 JVM 的初始化完成...
-
8
一、编译流程预处理:根据以字符#开头的命令,修改原始的C程序。例如:第一行中的#include xxx命令告诉预处理器要读取头文件的内容,并把它直接插入程序文本中。最终得到.i文件编译:将文本文件.i翻译成文本文件.s,它包含汇编语言程序汇...
-
8
某小厂面试:String 类型的变量和常量做“+”运算时发生了什么?| JavaGuide思特沃克软件技术(武汉)有限公司 软件工程师本文已经收录进 Github 110k+ 点赞...
-
2
Roslyn 入门:使用 .NET Core 版本的 Roslyn 编译并执行跨平台的静态的源码 发布于 2018-05-25 21:24 更新于 2021-08-30 02:40 ...
-
2
请问java中通过命令行执行c的.out编译文件时,找不到c类库的目录应该如何解决 - OSCHINA - 中文开源技术交流社区 开...
-
6
Home Menu...
-
20
Hi!大家好,我是神 Q 超人!我想点进来的大家应该都听过,也在浏览器或 Node.js 上执行过 JavaScript,但你们有想过 JavaScript 是如何执行的吗?这背后的功臣就是 JavaScrip...
-
5
中国人寿,被强行执行44元!发生了什么? 中国人寿,被强行执行44元!发生了什么? 来源: 浏览:1387 2022-06-16 16:05:20 6月16日,据企查查显示,中国人寿保险股...
-
10
linux下的编译、链接、加载执行 作者: 邹成卓 2023-12-23 13:40:52 分类:
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK