关于Java的编译执行与解释执行
机器语言是最底层的语言,能够直接执行。而我们编写的源代码是人类语言, 计算机只能识别某些特定的二进制指令,在程序真正运行之前必须将源代码转换成二进制指令。
高级语言编程的程序有三种执行方式:
理解Java的几个编译器
前端编译器:把.java文件转变成.class文件。包括Sun的Javac、Eclipse JDT中的增量式编辑器(ECJ)
后端运行期即时编译器(JIT编译器,Just In Time Compiler):把字节码转成机器码。包括HotSpot VM的C1、C2编译器
静态提前编译器(AOT编译器,Ahead Of Time Compiler):把*.java编译成本地机器码。包括GNU Compiler for the Java(GCJ)、Excelsior JET
Java采用的是解释和编译混合的模式
在编译时期,我们通过将源代码编译成.class ,配合JVM这种跨平台的抽象,屏蔽了底层计算机操作系统和硬件的区别,实现了“一次编译,到处运行” 。 而在运行时期,目前主流的JVM 都是混合模式(-Xmixed),即解释运行 和编译运行配合使用。
Java一开始被定位为“解释执行”的语言,但是现在主流的虚拟机中都包含了即时编译器JIT。
程序从源代码到运行经历阶段:java程序--(编译javac)-->字节码文件.class-->类装载子系统化身为反射类Class--->运行时数据区--->(解释执行+JIT编译器编译)-->操作系统(Win,Linux,Mac JVM)。
.class文件就是可以到处运行的文件。然后Java字节码会被转化为目标机器代码,这是是由JVM来执行的,即Java的第二次编译。
Java采用的是解释和编译混合的模式:基于JVM执行引擎当中的解释器interpreter与即使编译器JIT共存

执行引擎获取到,由javac将源码编译成字节码文件class.
然后在运行的时候通过解释器interpreter转换成最终的机器码。(解释型)
另外JVM平台支持一种叫作即时编译的技术。即时编译的目的是避免函数被解释执行,而是将整个函数体编译成为机器码,这种方式可以使执行效率大幅度提升(直接编译型)

JIT将字节码转换成最终的机器码:
以 Oracle JDK提供的HotSpot虚拟机为例,在HotSpot虚拟机中,提供了两种编译模式:解释执行 和 即时编译(JIT,Just-In-Time)。
解释执行即逐条翻译字节码为可运行的机器码,而即时编译则以方法为单位将字节码翻译成机器码(上述提到的“编译执行”)。前者的优势在于不用等待,后者则在实际运行当中效率更高。
即时编译存在的意义在于它是提高程序性能的重要手段之一。根据“二八定律”(即:百分之二十的代码占据百分之八十的系统资源),对于大部分不常用的代码,我们无需耗时间将之编译为机器码,而是采用解释执行的方式,用到就去逐条解释运行;对于一些仅占据小部分的热点代码(可认为是反复执行的重要代码),则可将之翻译为符合机器的机器码高效执行,提高程序的效率,此为运行时的即时编译。
为了满足不同的场景,HotSpot虚拟机内置了多个即时编译器:C1,C2与Graal。Graal 是Java10正式引入的实验性即时编译器,在此暂不叙述(其实我不是很了解,尴尬···)。先看一下C1、C2 ,相信大家或多或少接触过。
- C1:即Client编译器,面向对启动性能有要求的客户端GUI程序,采用的优化手段比较简单,因此编译的时间较短。
- C2:即Server编译器,面向对性能峰值有要求的服务端程序,采用的优化手段复杂,因此编译时间长,但是在运行过程中性能更好。
从Java7开始,HotSpot虚拟机默认采用分层编译的方式:热点方法首先被C1编译器编译,而后 热点方法中的热点再进一步被C2编译,根据前面的运行计算出更优的编译优化。为了不干扰程序的正常运行,JIT编译时放在额外的线程中执行的,HotSpot根据实际CPU的资源,以 1:2的比例分配给C1和C2线程数。在计算机资源充足的情况,字节码的解释运行和编译运行时可以同时进行,JIT编译执行完后的机器码会在下次调用该方法时启动,已替换原本的解释执行(意思就是已经翻译出效率更高的机器码,自然替换原来的相对低效率执行的方法)。
以上,可以看出在Java中不单单是解释执行,即时编译(编译执行)在Java性能优化中彰显重要的作用,所以现在应该说:Java是解释执行和编译执行共同存在的,至少大部分是这样。
编译与解释比较?
1.一段程序编译会浪费时间,并且移植到其他平台上时还要进行重新编译,但是其编译后生成的可执行文件运行速度快。
2.解释型程序可跨平台执行,无需将全部代码编译之后再运行,能够及时运行,但因为是逐条解释执行所以最终的运行速度不如编译型程序。
3.内存使用:编译执行需要生成编译后的机器码文件,而解释执行时逐句解释执行,所以解释执行对内存占用更少。
单独使用解释器的缺点:
抛弃了JIT可能带来的性能优势。如果代码没有被JIT编译的话,再次运行时需要重复解析。
单独使用JIT编译器的缺点:
需要将全部的代码编译成本地机器码。要花更多的时间,JVM启动会变慢非常多;
增加可执行代码的长度(字节码比JIT编译后的机器码小很多),这将导致页面调度,从而降低程序的速度。
有些JIT编译器的优化方式,比如分支预测,如果不进行profiling,往往并不能进行有效优化。
因此,HotSpot采用了惰性评估(Lazy Evaluation)的做法,根据二八定律,消耗大部分系统资源的只有那一小部分的代码(热点代码),而这也就是JIT所需要编译的部分。JVM会根据代码每次被执行的情况收集信息并相应地做出一些优化,因此执行的次数越多,它的速度就越快。
JDK 9引入了一种新的编译模式AOT(Ahead of Time Compilation),它是直接将字节码编译成机器码,这样就避免了JIT预热等各方面的开销。JDK支持分层编译和AOT协作使用。
注:JIT为方法级,它会缓存编译过的字节码在CodeCache中,而不需要被重复解释。
关于Java的编译执行与解释执行的更多相关文章
- JAVA,Python代码是编译执行还是解释执行?
转载地址:http://blog.csdn.net/zv3e189os5c0tsknrbcl/article/details/78661641 有人在讨论 Python 代码是编译执行还是解释执行?这 ...
- 关于python代码是编译执行还是解释执行
Python 是编译型语言还是解释型语言?回答这个问题前,应该先弄清楚什么是编译型语言,什么是解释型语言. 所谓编译执行就是源代码经过编译器编译处理,生成目标机器码,就是机器能直接运行的二进制代码,下 ...
- JAR-使用JAVA命令编译打包一个可执行jar包
一.开发一个演示项目 项目源代码开发 项目名称叫jar-package-example(其实只是一个文件夹, 用以将演示的所有文件夹和文件存放在其中, 没啥其它作用), 为了方便, 后文统一叫jar- ...
- 编译执行 VS 解释执行
一般编译程序从对源程序执行途径的角度不同,可分为解释执行和编译执行. 所谓解释执行是借助于解释程序完成,即按源程序语句运行时的动态结构,直接逐句地边分析边翻译并执行.像自然语言翻译中的口译,随时进行翻 ...
- Java解释执行和编译执行
以前有句话说:“Java是解释执行的 ” .现在看来确实不是很准确,至于原因,在此简略解释: 首先,我们先解释一下在Java中解释执行和编译执行的区别. 解释执行:将编译好的字节码一行一行地翻译为机器 ...
- 面试官:Java从编译到执行,发生了什么?
面试官:今天从基础先问起吧,你是怎么理解Java是一门「跨平台」的语言,也就是「一次编译,到处运行的」? 候选者:很好理解啊,因为我们有JVM. 候选者:Java源代码会被编译为class文件,cla ...
- F# 既能解释执行,也能编译执行
F# 除了是函数式语言和面向对象语言之外,还有个突出的特点是:既能解释执行,也能编译执行. 一般说来,一种语言只能选择其一种.比如说C++.C#是编译执行,不能解释执行,象Matlab.R是解释执 ...
- jvm的解释执行与编译执行
1.原理 字节码无法直接交给硬件执行需要虚拟机翻译成机器码才能执行,“翻译”的策略有两种:解释执行和编译执行又称即使编译(JIT).解释执行是没执行一句字节码的时候把字节码翻译成机器码并执行,优点是启 ...
- JAVA虚拟机:虚拟机字节码执行引擎
“虚拟机”是一个相对“物理机”的概念,这两种机器都有代码执行能力. 物理机的执行引擎是直接建立在处理器.硬件.指令集和操作系统层面上的. 虚拟机的执行引擎由自己实现,自行制定指令集与执行引擎的结构体系 ...
随机推荐
- Pytorch_第十篇_卷积神经网络(CNN)概述
卷积神经网络(CNN)概述 Introduce 卷积神经网络(convolutional neural networks),简称CNN.卷积神经网络相比于人工神经网络而言更适合于图像识别.语音识别等任 ...
- fatal: 远程 origin 已经存在 | 关于git push 详解
fatal: 远程 origin 已经存在. 解决方法1:删除origin主机名 git remote rm origin #删除 git remote add origin https://gith ...
- xss-labs 通关学习笔记
xss-labs 学习 By:Mirror王宇阳 time:2020/04/06 level1 我们进入到这个页面之后,快速关注到几个点,Xss注重的输入点,这里的输入点首先在URL栏中找到了name ...
- Python网络爬虫与信息提取笔记
直接复制粘贴笔记发现有问题 文档下载地址//download.csdn.net/download/hide_on_rush/12266493 掌握定向网络数据爬取和网页解析的基本能力常用的 Pytho ...
- Spark中遇到的问题
spark启动slave时提示 JAVA_HOME is not set 解决方法: 在sbin目录spark-config.sh 中添加自己的jdk 路径export JAVA_HOME=/home ...
- Linux内核之 内存管理
前面几篇介绍了进程的一些知识,从这篇开始介绍内存.文件.IO等知识,发现更不好写哈哈.但还是有必要记录下自己的所学所思.供后续翻阅,同时写作也是一个巩固的过程. 这些知识以前有文档涉及过,但是角度不同 ...
- MyISAM 和InnoDB的区别
InnoDB和MyISAM是许多人在使用MySQL时最常用的两个表类型,这两个表类型各有优劣,视具体应用而定.基本的差别为:MyISAM类型不支持事务处理等高级处理,而InnoDB类型支持.MyISA ...
- Debian 镜像使用帮助
链接: Debian 镜像使用帮助 buster: # 默认注释了源码镜像以提高 apt update 速度,如有需要可自行取消注释 deb https://mirrors.tuna.tsinghua ...
- 操作系统-文件系统(5)Linux文件系统管理
主流分区机制有MBR和GPT两种 MBR分区:第一个扇区最重要,里面有:引导代码(Bootstrap code area)及分区表(partition table), 其中Bootstrap code ...
- DBeaver链接kerberos安全认证的Phoenix集群
DBeaver链接kerberos安全认证的Phoenix集群 最近公司的CDH集群,启动了kerberos安全认证,所有的用户验证全部需要依赖kerberos来进行.之前的裸奔集群,总算有了一些安全 ...