终于搞懂了JIT
Java这个语言很非凡。
一、你可以说它是编译型的。因为所有的Java代码都是要编译的,.java不经过编译就什么用都没有。 二、你可以说它是解释型的。因为java代码编译后不能直接运行,它是解释运行在JVM上的,所以它是解释运行的,那也就算是解释的了。
三、但是,现在的JVM为了效率,都有一些JIT优化。它又会把.class的二进制代码编译为本地的代码直接运行,所以,又是编译的。
像C、C++ 他们经过一次编译之后直接可以编译成操作系统了解的类型,可以直接执行的 所以他们是编译型的语言。没有经过第二次的处理 而Java不一样他首先由编译器编译成.class类型的文件,这个是java自己类型的文件 然后在通过虚拟机(JVM)从.class文件中读一行解释执行一行,所以他是解释型的语言,而由于java对于多种不同的操作系统有不同的JVM所以 Java实现了真正意义上的跨平台!
请观看下面两张图 了解一下Java的虚拟机机制:
(1)java语言的编译-->解释--->执行过程
(2)java的虚拟机
今天听到同事在讨论java是哪种类型的语言(编译型、解释型),以前稍微有些接触,但是概念比较模糊,为了不至于让别人的思想左右自己,所以查了些资料,找到了很多热心网友给出的答案,终于有些明白。这里先给出编译型语言和解释型语言的定义。
定义:
编译型语言:把做好的源程序全部编译成二进制代码的可运行程序。然后,可直接运行这个程序。
解释型语言:把做好的源程序翻译一句,然后执行一句,直至结束!
区别:
编译型语言,执行速度快、效率高;依靠编译器、跨平台性差些。
解释型语言,执行速度慢、效率低;依靠解释器、跨平台性好。
个人认为,java是解释型的语言,因为虽然java也需要编译,编译成.class文件,但是并不是机器可以识别的语言,而是字节码,最终还是需要 jvm的解释,才能在各个平台执行,这同时也是java跨平台的原因。所以可是说java即是编译型的,也是解释型,但是假如非要归类的话,从概念上的定义,恐怕java应该归到解释型的语言中。
附:
编译型的语言包括:C、C++、Delphi、Pascal、Fortran
解释型的语言包括:Java、Basic、javascript
定义:
编译型语言:把做好的源程序全部编译成二进制代码的可运行程序。然后,可直接运行这个程序。
解释型语言:把做好的源程序翻译一句,然后执行一句,直至结束!
区别:
编译型语言,执行速度快、效率高;依靠编译器、跨平台性差些。
解释型语言,执行速度慢、效率低;依靠解释器、跨平台性好。
个人认为,java是解释型的语言,因为虽然java也需要编译,编译成.class文件,但是并不是机器可以识别的语言,而是字节码,最终还是需要 jvm的解释,才能在各个平台执行,这同时也是java跨平台的原因。所以可是说java即是编译型的,也是解释型,但是假如非要归类的话,从概念上的定义,恐怕java应该归到解释型的语言中。
附:
编译型的语言包括:C、C++、Delphi、Pascal、Fortran
解释型的语言包括:Java、Basic、javascript
在部分的商用虚拟机中,Java 程序最初是通过解释器( Interpreter )进行解释执行的,
当虚拟机发现某个方法或代码块的运行特别频繁的时候,就会把这些代码认定为“热点代码”。
为了提高热点代码的执行效率,在运行时,即时编译器(Just In Time Compiler )会把这些代码编译成与本地平台相关的机器码,并进行各种层次的优化。
1、HotSpot 内的即时编译器
解释器和编译器各有各的优点:
解释器优点:当程序需要迅速启动的时候,解释器可以首先发挥作用,省去了编译的时间,立即执行。解释执行占用更小的内存空间。同时,当编译器进行的激进优化失败的时候,还可以进行逆优化来恢复到解释执行的状态。
编译器优点:在程序运行时,随着时间的推移,编译器逐渐发挥作用,把越来越多的代码编译成本地代码之后,可以获得更高的执行效率。
因此,整个虚拟机执行架构中,解释器与编译器经常配合工作,如下图所示。
HotSpot中内置了两个即时编译器,分别称为 Client Compiler和 Server Compiler ,或者简称为 C1 编译器和 C2 编译器。目前的 HotSpot 编译器默认的是解释器和其中一个即时编译器配合的方式工作,具体是哪一个编译器,取决于虚拟机运行的模式,HotSpot 虚拟机会根据自身版本与计算机的硬件性能自动选择运行模式,用户也可以使用 -client 和 -server 参数强制指定虚拟机运行在 Client 模式或者 Server 模式。这种配合使用的方式称为“混合模式”(Mixed Mode),用户可以使用参数 -Xint 强制虚拟机运行于 “解释模式”(Interpreted Mode),这时候编译器完全不介入工作。另外,使用 -Xcomp 强制虚拟机运行于 “编译模式”(Compiled Mode),这时候将优先采用编译方式执行,但是解释器仍然要在编译无法进行的情况下接入执行过程。通过虚拟机 -version 命令可以查看当前默认的运行模式。
2、被编译对象和触发条件
在运行过程中会被即时编译的“热点代码”有两类,即:
- 被多次调用的方法
- 被多次执行的循环体
对于第一种,编译器会将整个方法作为编译对象,这也是标准的JIT 编译方式。对于第二种是由循环体出发的,但是编译器依然会以整个方法作为编译对象,因为发生在方法执行过程中,称为栈上替换。
判断一段代码是否是热点代码,是不是需要出发即时编译,这样的行为称为热点探测(Hot Spot Detection),探测算法有两种,分别为。
- 基于采样的热点探测(Sample Based Hot Spot Detection):虚拟机会周期的对各个线程栈顶进行检查,如果某些方法经常出现在栈顶,这个方法就是“热点方法”。好处是实现简单、高效,很容易获取方法调用关系。缺点是很难确认方法的reduce,容易受到线程阻塞或其他外因扰乱。
- 基于计数器的热点探测(Counter Based Hot Spot Detection):为每个方法(甚至是代码块)建立计数器,执行次数超过阈值就认为是“热点方法”。优点是统计结果精确严谨。缺点是实现麻烦,不能直接获取方法的调用关系。