从java文件到字节码

本文来说一下,我们开发好的.java文件是源码文件,并不能交给机器直接执行,需要将其变成字节码甚至是机器码文件。那么静态编译器是如何把源码转化成字节码的呢?

下图为.java源码转化为字节码的过程。

词法解析就是通过空格分隔出单词、操作符、控制符等信息,将其形成token信息流,传递给语法解析器;在语法解析时,把词法解析得到的token信息流按照Java语法规则组装成一个语法树。

如上图虚线框中所示;在语义分析阶段,需要检查关键字的使用是否合理、类型是否合理、作用域是否正确等。当语义分析完成之后,即可以生成字节码。

字节码必须通过类加载过程加载到JVM环境中后,才可以执行。

字节码执行的三种模式

  1. 解释执行
  2. JIT编译执行
  3. JIT编译与解释混合执行(主流JVM默认模式)

何为JIT编译?

  • 动态编译(dynamic compilation)指的是“在运行时进行编译”;与之相对的是事前编译(ahead-of-time compilation,简称AOT),也叫静态编译(static compilation)。
  • JIT编译(just-in-time compilation)狭义来说是当某段代码即将第一次被执行时进行编译,因而叫“即时编译”。JIT编译是动态编译的一种特例。JIT编译一词后来被泛化,时常与动态编译等价;但要注意广义与狭义的JIT编译所指的区别。
  • 自适应动态编译(adaptive dynamic compilation)也是一种动态编译,但它通常执行的时机比JIT编译迟,先让程序“以某种式”先运行起来,收集一些信息之后再做动态编译。这样的编译可以更加优化。

混合执行模式的优势在于解释器在启动时先解释执行,省去编译时间。随着时间推进,JVM通过热点代码统计分析,识别高频的方法调用、循环体、公共模块等。JIT的作用就是将Java字节码动态低编译成可以直接发送给处理器指令执行的机器码。大致流程如下:

注意:解释执行与编译执行在线上环境微妙的辩证关系。机器在热机状态可以承受的负载大于冷机状态(刚刚启动的时候),如果以热机状态的流量进行切流,可能会导致处于冷机状态的服务器因无法承受流量而假死。在生产环境发布过程中,以分批的方式进行发布,根据机器数量划分成多个批次,建议每个批次的机器数之多占到整个集群的12.5%(1/8)。曾经有这样的故障案例:某程序员在发布平台进行分批发布,在输入发布总批次数的时候,误填写成分两批发布。如果是热机状态,在正常情况下一半的机器可以勉强承载流量,但是由于刚刚启动的JVM均是解释执行,还没有进行热点代码统计和JIT动态编译,导致机器启动之后,当前1/2发布成功的服务器马上全军覆没,此次故障说明了JIT的存在。

下篇说类加载过程,敬请期待!

本文分享自微信公众号 - Java后端技术栈(t-j20120622)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-09-09

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏携程技术中心

干货 | 加载速度提升15%,携程对RN新一代JS引擎Hermes的调研

储贻锋,携程无线平台研发部基础框架组资深Android研发,目前主要负责CRN Android端和携程Android基础架构的维护与开发工作。

43240
来自专栏一名叫大蕉的程序员

靠转型大数据涨薪的日子一去不复返了 No.156

在 2013 年,大数据刚刚崭露头角,有一大批程序员,在那个时间点,踏上了靠转型大数据升职加薪的日子。在那个时候,只要稍微懂一点点 Hadoop,会写一点点 H...

9430
来自专栏白石

Java 8 Java.Time Package: 解析任何字符串到日期格式对象

​ 我的一个项目,我收到一个要求: 解析一个文本文件,字符串表示的日期或时间戳将有许多不同的格式,不提前知道,然而他们都代表一个有效的日期或时间戳需要正确...

8820
来自专栏白石

非Spring环境下的Ribbon+Feign使用宝典

Ribbon是一个负载均衡客户端,可以很好的控制http和tcp的一些行为,一般都是Ribbon搭配Feign一起使用;Feign默认集成了ribbon

9940
来自专栏泰斗贤若如

Mybatis案例超详解(上)

本来是想像之前一样继续跟新Mybatis,但由于种种原因,迟迟没有更新,快开学了,学了一个暑假,博客也更新了不少,我觉得我得缓缓,先整合一些案例练练,等我再成...

11930
来自专栏攻城狮的那点事

你真的理解 Integer 的缓存问题吗?

问原因则随口就说”Integer缓存了-128到127之间的整数对象“,为什么会缓存?还有其他答案?可能就不知道了。

12920
来自专栏白石

在使用Java 8并行流之前要考虑两次

如果您倾听来自Oracle的人们谈论Java 8背后的设计选择,您会经常听到并行性是主要动机。 并行化是lambdas,流API和其他方面的驱动力。 我们来看一...

16740
来自专栏码匠的流水账

聊聊dubbo的ForkingClusterInvoker

dubbo-2.7.3/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/For...

11300
来自专栏白石

Groovy操纵集合秘籍

例如:我们需要得到一个集合对象,它的每一个元素是list对象的每一个元素的两倍 java风格:

13720
来自专栏白石

Groovy-拾遗

许多以前使用 C++ 的开发人员会怀念操作符重载,例如 + 和 -。虽然它们很方便,但是被覆盖的操作符的多态实质会造成混淆,所以操作符重载在 Java 语言中被...

9420

扫码关注云+社区

领取腾讯云代金券

年度创作总结 领取年终奖励