面试官:Java从编译到执行,发生了什么?

BitPathfinder
• 阅读 2865

面试官:今天从基础先问起吧,你是怎么理解Java是一门「跨平台」的语言,也就是「一次编译,到处运行的」?

候选者:很好理解啊,因为我们有JVM。

候选者:Java源代码会被编译为class文件,class文件是运行在JVM之上的。

候选者:当我们日常开发安装JDK的时候,可以发现JDK是分「不同的操作系统」,JDK里是包含JVM的,所以Java依赖着JVM实现了『跨平台』

候选者:JVM是面向操作系统的,它负责把Class字节码解释成系统所能识别的指令并执行,同时也负责程序运行时内存的管理。

面试官:Java从编译到执行,发生了什么?

面试官那要不你来聊聊从源码文件(.java)到代码执行的过程呗?

候选者:嗯,没问题的

候选者:简单总结的话,我认为就4个步骤:编译->加载->解释->执行

候选者:编译:将源码文件编译成JVM可以解释的class文件。

候选者:编译过程会对源代码程序做 「语法分析」「语义分析」「注解处理」等等处理,最后才生成字节码文件。

候选者:比如对泛型的擦除和我们经常用的Lombok就是在编译阶段干的。

面试官:Java从编译到执行,发生了什么?

候选者:加载:将编译后的class文件加载到JVM中。

候选者:在加载阶段又可以细化几个步骤:装载->连接->初始化

候选者:下面我对这些步骤又细说下哈。

面试官:Java从编译到执行,发生了什么?

候选者:【装载时机】为了节省内存的开销,并不会一次性把所有的类都装载至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的静态变量、静态代码块、静态方法至()方法,随后从上往下开始执行。

候选者:如果「实例化对象」则会调用方法对实例变量进行初始化,并执行对应的构造方法内的代码。

面试官:Java从编译到执行,发生了什么?

候选者:扯了这么多,现在其实才完成至(编译->加载->解释->执行)中的加载阶段,下面就来说下【解释阶段】做了什么

候选者:初始化完成之后,当我们尝试执行一个类的方法时,会找到对应方法的字节码的信息,然后解释器会把字节码信息解释成系统能识别的指令码。

候选者:「解释」这个阶段它做的事情可以总结为:把字节码转换为操作系统识别的指令

候选者:在解释阶段会有两种方式把字节码信息解释成机器指令码,一个是字节码解释器、一个是即时编译器(JIT)。

面试官:Java从编译到执行,发生了什么?

候选者:JVM会对「热点代码」做编译,非热点代码直接进行解释。当JVM发现某个方法或代码块的运行特别频繁的时候,就有可能把这部分代码认定为「热点代码」

候选者:使用「热点探测」来检测是否为热点代码。「热点探测」一般有两种方式,计数器和抽样。HotSpot使用的是「计数器」的方式进行探测,为每个方法准备了两类计数器:方法调用计数器和回边计数器

候选者:这两个计数器都有一个确定的阈值,当计数器超过阈值溢出了,就会触发JIT编译。

候选者:即时编译器把热点方法的指令码保存起来,下次执行的时候就无需重复的进行解释,直接执行缓存的机器语言

面试官:嗯…

候选者:解释阶段结束后,最后就到了执行阶段。

候选者:「执行」这个阶段它做的事情可以总结为:操作系统把解释器解析出来的指令码,调用系统的硬件执行最终的程序指令。

候选者:上面就是我对从源码文件(.java)到代码执行的过程的理解了。

面试官:嗯…我还想问下你刚才提到的双亲委派模型…

候选者:下次一定!

面试官:Java从编译到执行,发生了什么?

本文总结:

  • Java跨平台因为有JVM屏蔽了底层操作系统
  • Java源码到执行的过程,从JVM的角度看可以总结为四个步骤:编译->加载->解释->执行

    • 「编译」经过 语法分析、语义分析、注解处理 最后才生成会class文件
    • 「加载」又可以细分步骤为:装载->连接->初始化。装载则把class文件装载至JVM,连接则校验class信息、分配内存空间及赋默认值,初始化则为变量赋值为正确的初始值。连接里又可以细化为:验证、准备、解析
    • 「解释」则是把字节码转换成操作系统可识别的执行指令,在JVM中会有字节码解释器和即时编译器。在解释时会对代码进行分析,查看是否为「热点代码」,如果为「热点代码」则触发JIT编译,下次执行时就无需重复进行解释,提高解释速度
    • 「执行」调用系统的硬件执行最终的程序指令

面试官:Java从编译到执行,发生了什么?

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

【对线面试官-移动端】系列 一周两篇持续更新中!

【对线面试官-电脑端】系列 一周两篇持续更新中!

原创不易!!求三连!!

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Jacquelyn38 Jacquelyn38
4年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Wesley13 Wesley13
3年前
FLV文件格式
1.        FLV文件对齐方式FLV文件以大端对齐方式存放多字节整型。如存放数字无符号16位的数字300(0x012C),那么在FLV文件中存放的顺序是:|0x01|0x2C|。如果是无符号32位数字300(0x0000012C),那么在FLV文件中的存放顺序是:|0x00|0x00|0x00|0x01|0x2C。2.  
Easter79 Easter79
3年前
Twitter的分布式自增ID算法snowflake (Java版)
概述分布式系统中,有一些需要使用全局唯一ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点,首先他相对比较长,另外UUID一般是无序的。有些时候我们希望能使用一种简单一些的ID,并且希望ID能够按照时间有序生成。而twitter的snowflake解决了这种需求,最初Twitter把存储系统从MySQL迁移
Wesley13 Wesley13
3年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
3年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Java服务总在半夜挂,背后的真相竟然是... | 京东云技术团队
最近有用户反馈测试环境Java服务总在凌晨00:00左右挂掉,用户反馈Java服务没有定时任务,也没有流量突增的情况,Jvm配置也合理,莫名其妙就挂了
Python进阶者 Python进阶者
1年前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这
美凌格栋栋酱 美凌格栋栋酱
5个月前
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(
BitPathfinder
BitPathfinder
Lv1
再相逢,相顾无言,却无泪千行。
文章
3
粉丝
0
获赞
0