面试官: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编译,下次执行时就无需重复进行解释,提高解释速度
- 「执行」调用系统的硬件执行最终的程序指令

欢迎关注我的微信公众号【Java3y】来聊聊Java面试,对线面试官系列持续更新中!

【对线面试官-移动端】系列 一周两篇持续更新中!
【对线面试官-电脑端】系列 一周两篇持续更新中!
原创不易!!求三连!!
面试官:Java从编译到执行,发生了什么?的更多相关文章
- Java 代码编译和执行的整个过程
Java 代码编译是由 Java 源码编译器来完成,流程图如下所示: Java 字节码的执行是由 JVM 执行引擎来完成,流程图如下所示: Java 代码编译和执行的整个过程包含了以下三个重要的机制: ...
- JVM学习笔记(二)------Java代码编译和执行的整个过程【转】
转自:http://blog.csdn.net/cutesource/article/details/5904542 版权声明:本文为博主原创文章,未经博主允许不得转载. Java代码编译是由Java ...
- JVM学习笔记(二)------Java代码编译和执行的整个过程
Java代码编译是由Java源码编译器来完成,流程图如下所示: Java字节码的执行是由JVM执行引擎来完成,流程图如下所示: Java代码编译和执行的整个过程包含了以下三个重要的机制: Java源码 ...
- Java代码编译和执行的整个过程
Java代码编译是由Java源码编译器来完成,流程图如下所示: Java字节码的执行是由JVM执行引擎来完成,流程图如下所示: Java代码编译和执行的整个过程包含了以下三个重要的机制: Java源码 ...
- JVM原理(Java代码编译和执行的整个过程+JVM内存管理及垃圾回收机制)
转载注明出处: http://blog.csdn.net/cutesource/article/details/5904501 JVM工作原理和特点主要是指操作系统装入JVM是通过jdk中Java.e ...
- 面试官:SpringBoot jar 可执行原理,知道吗?
文章篇幅较长,但是包含了SpringBoot 可执行jar包从头到尾的原理,请读者耐心观看.同时文章是基于 SpringBoot-2.1.3进行分析.涉及的知识点主要包括Maven的生命周期以及自定义 ...
- java代码的编译、执行过程
Java代码编译是由Java源码编译器来完成,流程图如下所示: Java字节码的执行是由JVM执行引擎来完成,流程图如下所示: Java代码编译和执行的整个过程包含了以下三个重要的机制: Java源码 ...
- AJPFX编写cmd界面下一键编译、执行java代码的bat脚本
此脚本适合刚接触java的同学,在cmd界面下用jc取代 复杂的 javac *.java + java main使用说明:把脚本内容复制到txt文本中,修改后缀名为.bat,运行一次即可完成配置, ...
- Java代码的编译和执行
Java代码编译和执行的整个过程包含了以下三个重要的机制: (1)Java源码编译机制 (2)类加载机制 (3)类执行机制 1.Java代码编译是由Java源码编译器来完成,流程图: Java 源码编 ...
随机推荐
- 将 VS2017下开发的程序, 部署到其他电脑上运行
关键步骤:设置Release,如下图 如果无法直接执行,则安装ALI213-Microsoft.Visual.C++.2017.Redistributable.Package.x86.x64
- n, n+1, ..., 2n 中的 5 数环初探
本篇是 IMO 2021 第一题题解及相关拓展问题分析 和 IMO 2021 第 1 题拓展问题的两个极值的编程求解 的延伸篇. 从上两篇的分析,可知: 当 n < 48 时,n, n+1, . ...
- tomcat配置启动不了
关于ideatomcat配置问题 1.第一步配置tomcat启动器 2.配置启动的网址 3.配置启动器的启动 ---更多java学习,请见本人小博客:https://zhangjzm.gitee.io ...
- Cookie在哪里看
更多java学习请进: https://zhangjzm.gitee.io/self_study
- sublime text 的 Ctrl + P「模糊搜索算法」
Reverse Engineering Sublime Text's Fuzzy Match 这是我能 google 到的最早的一篇关于 Sublime Text 的模糊搜索的文章. https:// ...
- 通过WebGoat学习java反序列化漏洞
首发于freebuff. WebGoat-Insecure Deserialization Insecure Deserialization 01 概念 本课程描述了什么是序列化,以及如何操纵它来执行 ...
- shp的基本操作
本节将介绍如何利用python完成对shp的基本操作 1.读取shp四至 import shapefile sf = shapefile.Reader(r"E:\shp\1.shp" ...
- SQL Server数据表设计编辑后无法保存处理办法
关于使用 SQL Server 企业管理器,表[设计]界面,修改数据表字段或类型无法保存的问题处理过程: 使用SQL Server数据库的你是否遇到过每次数据库编辑工具内点击设计修改表字段或类型要保存 ...
- SQL-UPDATE触发器练习
&练习一 如下所示三张表( student,grade,student_updata_before ): student表 grade表 Student_update_before表 # 触发 ...
- 【Nginx】Linux常用命令------启动、停止、重启
启动 启动代码格式:nginx安装目录地址 -c nginx配置文件地址 例如: [root@LinuxServer sbin]# /usr/local/nginx/sbin/nginx -c /us ...