java语言 编译原理_【Java学习】深入分析Java的编译原理

在《Java代码的编译与反编译》中,有过关于Java语言的编译和反编译的介绍。我们可以通过javac命令将Java程序的源代码编译成Java字节码,即我们常说的class文件。这是我们通常意义上理解的编译。

但是,字节码并不是机器语言,要想让机器能够执行,还需要把字节码翻译成机器指令。这个过程是Java虚拟机做的,这个过程也叫编译。是更深层次的编译。

在编译原理中,把源代码翻译成机器指令,一般要经过以下几个重要步骤:

bf8e430558034495a4c76a090f46b23e.png

根据完成任务不同,可以将编译器的组成部分划分为前端(Front End)与后端(Back End)。

前端编译主要指与源语言有关但与目标机无关的部分,包括词法分析、语法分析、语义分析与中间代码生成。

后端编译主要指与目标机有关的部分,包括代码优化和目标代码生成等。

我们可以把将.java文件编译成.class的编译过程称之为前端编译。把将.class文件翻译成机器指令的编译过程称之为后端编译。

Java中的前端编译

前端编译主要指与源语言有关但与目标机无关的部分,包括词法分析、语法分析、语义分析与中间代码生成。

我们所熟知的javac的编译就是前端编译。除了这种以外,我们使用的很多IDE,如eclipse,idea等,都内置了前端编译器。主要功能就是把.java代码转换成.class代码。

词法分析

词法分析阶段是编译过程的第一个阶段。这个阶段的任务是从左到右一个字符一个字符地读入源程序,将字符序列转换为标记(token)序列的过程。这里的标记是一个字符串,是构成源代码的最小单位。在这个过程中,词法分析器还会对标记进行分类。

词法分析器通常不会关心标记之间的关系(属于语法分析的范畴),举例来说:词法分析器能够将括号识别为标记,但并不保证括号是否匹配。

语法分析

语法分析的任务是在词法分析的基础上将单词序列组合成各类语法短语,如“程序”,“语句”,“表达式”等等.语法分析程序判断源程序在结构上是否正确.源程序的结构由上下文无关文法描述。

语义分析

语义分析是编译过程的一个逻辑阶段, 语义分析的任务是对结构上正确的源程序进行上下文有关性质的审查,进行类型审查。语义分析是审查源程序有无语义错误,为代码生成阶段收集类型信息。

语义分析的一个重要部分就是类型检查。比如很多语言要求数组下标必须为整数,如果使用浮点数作为下标,编译器就必须报错。再比如,很多语言允许某些类型转换,称为自动类型转换。

中间代码生成

在源程序的语法分析和语义分析完成之后,很多编译器生成一个明确的低级的或类机器语言的中间表示。该中间表示有两个重要的性质: 1.易于生成; 2.能够轻松地翻译为目标机器上的语言。

在Java中,javac执行的结果就是得到一个字节码,而这个字节码其实就是一种中间代码。

PS:著名的解语法糖操作,也是在javac中完成的。

Java中的后端编译

首先,我们大家都知道,通常通过 javac 将程序源代码编译,转换成 java 字节码,JVM 通过解释字节码将其翻译成对应的机器指令,逐条读入,逐条解释翻译。很显然,经过解释执行,其执行速度必然会比可执行的二进制字节码程序慢很多。这就是传统的JVM的解释器(Interpreter)的功能。为了解决这种效率问题,引入了 JIT 技术。

JAVA程序还是通过解释器进行解释执行,当JVM发现某个方法或代码块运行特别频繁的时候,就会认为这是“热点代码”(Hot Spot Code)。然后JIT会把部分“热点代码”翻译成本地机器相关的机器码,并进行优化,然后再把翻译后的机器码缓存起来,以备下次使用。

HotSpot虚拟机中内置了两个JIT编译器:Client Complier和Server Complier,分别用在客户端和服务端,目前主流的HotSpot虚拟机中默认是采用解释器与其中一个编译器直接配合的方式工作。

当 JVM 执行代码时,它并不立即开始编译代码。首先,如果这段代码本身在将来只会被执行一次,那么从本质上看,编译就是在浪费精力。因为将代码翻译成 java 字节码相对于编译这段代码并执行代码来说,要快很多。第二个原因是最优化,当 JVM 执行某一方法或遍历循环的次数越多,就会更加了解代码结构,那么 JVM 在编译代码的时候就做出相应的优化。

在机器上,执行java -version命令就可以看到自己安装的JDK中JIT是哪种模式:

1847de2a62cd7147a1d608810dd5c92a.png

上图是我的机器上安装的jdk1.8,可以看到,他是Server Compile,但是,需要说明的是,无论是Client Complier还是Server Complier,解释器与编译器的搭配使用方式都是混合模式,即上图中的mixed mode。

热点检测

上面我们说过,要想触发JIT,首先需要识别出热点代码。目前主要的热点代码识别方式是热点探测(Hot Spot Detection),有以下两种:

1、基于采样的方式探测(Sample Based Hot Spot Detection) :周期性检测各个线程的栈顶,发现某个方法经常出险在栈顶,就认为是热点方法。好处就是简单,缺点就是无法精确确认一个方法的热度。容易受线程阻塞或别的原因干扰热点探测。

2、基于计数器的热点探测(Counter Based Hot Spot Detection)。采用这种方法的虚拟机会为每个方法,甚至是代码块建立计数器,统计方法的执行次数,某个方法超过阀值就认为是热点方法,触发JIT编译。

在HotSpot虚拟机中使用的是第二种——基于计数器的热点探测方法,因此它为每个方法准备了两个计数器:方法调用计数器和回边计数器。

方法计数器。顾名思义,就是记录一个方法被调用次数的计数器。

回边计数器。是记录方法中的for或者while的运行次数的计数器。

编译优化

前面提到过,JIT除了具有缓存的功能外,还会对代码做各种优化。说到这里,不得不佩服HotSpot的开发者,他们在JIT中对于代码优化真的算是面面俱到了。

这里简答提及几个我觉得比较重要的优化技术,并不准备直接展开,读者感兴趣的话,我后面再写文章单独介绍。

逃逸分析、 锁消除、 锁膨胀、 方法内联、 空值检查消除、 类型检测消除、 公共子表达式消除

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/460214.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

实验 使用 vivado zedboard GPIO 开关 开控制 LED

前面我做了几个实验 都没有用过 开关,这一次用一用 发现 vivado 真的挺方便 所以 使用 vivado 开发 1.建工程 我使用 vivado 2013.4 创建新工程 –》 next –》next 勾选 Do not specify sources at this time //这样跳过后面两个添加文件页面 选择 board –》 ze…

java 最优化_java-多维度求最优解

拿出11条数据//条件每个位置(position)的人数限制每队(team)人数不能超过7人credits的总和在100分之内(包含100)总分(points)最高//位置人数限制position-1 : 1 position-2 : 3-5 position-3 : 1-3 position-4 : 3-5//模拟数据{points credits position team56 9.0 1 t154 9.1 …

必应(Bing)每日图片获取API

必应(Bing)每日图片获取API January 11, 2015 API http://lab.dobyi.com/api/bing.php 介绍 ValueDescriptiontitle标题desc描述url图片地址你们自由发挥……

java取模多位数_JAVA大数类—基础操作(加减乘除、取模、四舍五入、设置保留位数)...

当基础数据类型长度无法满足需求时可以使用大数类构造方法接受字符串为参数1 BigInteger bInt new BigInteger("123123");2 BigDecimal bDouble new BigDecimal("123123.123123124");基础操作(取模使用divideAndRemainder方法,返回的数组第二…

HDU 4902

数据太弱&#xff0c;直接让我小暴力一下就过了&#xff0c;一开始没注意到时间是15000MS&#xff0c;队友发现真是太给力了 #include <cstdio> #include <cstring> int n,q,a[100005],x[100005],p,l[100005],r[100005],t[100005]; int tree[1000005]; void build(…

tcp/udp高并发和高吐吞性能测试工具

在编写一个网络服务的时候都比较关心这个服务能达到多少并发连接,而在这连接的基础上又能达到一个怎样的交互能力.编写服务已经是一件很花力气的事情,而还要去编写一个能够体现结果的测试工具就更加消耗工作时间.下面介绍一个测试工具只需要简单地设置一下就能对tcp/udp服务进行…

几个数字的和

ctrl z 的使用 #include<iostream> using namespace std;main() {int num,sum0;while(cin>>num) {sumnum;}cout<<"和为"<<sum<<endl; } View Code#include<iostream> using namespace std; main() { int num,s…

网站在线压力测试工具Load Impact

关于Load ImpactLoad Impact是一个一个在线的网站压力测试服务及工具&#xff0c;模拟多用户同时访问你的站点&#xff0c;并出具报告以分析你的站点可以支撑的访问者数量&#xff0c;它能让你通过简单的几次点击就能测试出你的网站的性能。不过免费用户只能同时并发50个虚拟访…

sc.next在java什么意思_sc.next() 和 nextLine 的原理

对java的Scanner类的next开头的相关类有点纠结&#xff0c;看了一些博客大致懂了&#xff0c;整理下代码事例直接参考了这位大佬的https://blog.csdn.net/long71751380/article/details/94008351. 总的原理以一段代码为例,scanner类import java.util.Scanner;public class Next…

WPF RichTextBox相关总结

由于公司涉及到聊天对话框的功能&#xff0c;就想到了RichTextBox&#xff0c;查阅相关资料&#xff0c;总结下&#xff1a; 一、RichTextBox的内容相关的类 1.1RichTextBox的内容结构 RichTexBox是个可编辑控件&#xff0c;可编辑我们很容易想到word的可编辑&#xff0c;在wor…

python 内置方法赋值_Python内置数据结构之字符串str

1. 数据结构回顾所有标准序列操作(索引、切片、乘法、成员资格检查、长度、最小值和最大值)都适用于字符串&#xff0c;但是字符串是不可变序列&#xff0c;因此所有的元素赋值和切片赋值都是非法的。>>> website http://www.python.org>>> website[-3:] c…

以下是关于ASP.NET中保存各种信息的对象的比较,理解这些对象的原理,对制作完善的程序来说是相当有必要的(摘至互联网,并非原创--xukunping)...

在ASP.NET中&#xff0c;有很多种保存信息的对象.例如:APPlication,Session,Cookie,ViewState和Cache等,那么它们有什么区别呢?每一种对象应用的环境是什么? 为了更清楚的了解,我们总结出每一种对象应用的具体环境,如下表所示: 方法信息量大小保存时间应用范围保存位置App…

实现每个点赞用户点击的带属性的字符串

2019独角兽企业重金招聘Python工程师标准>>> #pragma mark - 点击各个点赞用户-(void)setClicked:(TweetCell *)cell andOSCTweet:(OSCTweet *)tweet {NSMutableAttributedString *attributedString [[NSMutableAttributedString alloc] initWithString:tweet.like…

xampp php5.6 7.1共存,New XAMPP with PHP 7.2.8, 7.1.20, 7.0.31 5.6.37

嗨&#xff0c;阿帕奇的朋友们&#xff01;We just released new versions of XAMPP for all platforms with the latest PHP versions: 7.2.8, 7.1.20, 7.0.31 & 5.6.37.您可以下载这些新版本http://www.apachefriends.org/download.html.7.2.8 / 7.1.20 / 7.0.31 / 5.6.3…

基于.net开发chrome核心浏览器【四】

原文:基于.net开发chrome核心浏览器【四】一&#xff1a; 上周去北京出差&#xff0c;给国家电网的项目做架构方案&#xff0c;每天都很晚睡&#xff0c;客户那边的副总也这样拼命工作。 累的不行了&#xff0c;直接导致第四篇文章没有按时发出来。 希望虚心学习1&#xff0c;小…

php5.6 pdo.dll 没有,php5.6没有pdo怎么办

php5.6没有pdo是因为在php5.6中php已经内置了pdo功能&#xff0c;只需要在php.ini文件中将“extensionphp_pdo_firebird.dll”等配置项打开即可。推荐&#xff1a;《PHP视频教程》php5.6中没有php.pdo.dll文件我下载的php 5.6要使用pdo模块&#xff0c;但是通过百度发现发现没有…

网页的背景图片代码

网页背景图片代码1.(最普遍类) <style>body{background-image:url(logo.gif);background-repeat:no-repeat;background-position:center}</style> 说明:以上代码为网页背景图片固定代码&#xff01;网页背景图片固定代码&#xff0c;这样&#xff0c;当向下拉网页时…

andriod 新建 Activity_ Form (详细设置)

参考&#xff1a; Starting Another Activity 去创建Activity New->Other->Android->Android Activity->BlankActivity&#xff1a; 输入对应的信息&#xff1a; 创建完毕后&#xff0c;可以看到新建了对应的 src下面的java文件 layout下面的xml 等等&#xff1a; …

php laypage,layui laypage组件常见用法总结

laypage 的使用非常简单&#xff0c;指向一个用于存放分页的容器&#xff0c;通过服务端得到一些初始值&#xff0c;即可完成分页渲染。核心方法&#xff1a; laypage.render(options) 来设置基础参数。一、laypage的常用基础参数layui.use([laypage], function () {laypage l…

Swift标识符和关键字

任何一种计算机语言都离不开标识符和关键字&#xff0c;下面我们将详细介绍Swift标识符和关键字。 标示符 标识符就是给变量、常量、方法、函数、枚举、结构体、类、协议等指定的名字。构成标识符的字母均有一定的规范&#xff0c;Swift语言中标识符的命名规则如下&#xff1a;…