共计 2384 个字符,预计需要花费 6 分钟才能阅读完成。
面试官 :明天从根底先问起吧, 你是怎么了解 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 面试,对线面试官系列继续更新中!
【对线面试官 - 挪动端】系列 一周两篇继续更新中!
【对线面试官 - 电脑端】系列 一周两篇继续更新中!
原创不易!!求三连!!