Java虚拟机(Java Virtual Machine),一种可以运行字节码的虚拟机,将字节码解释成不一样os下的机器指令,有了jvm,java语言在不一样平台上运行时不须要从新编译,即平台无关性。前端
原理:编译后的 Java 程序指令并不直接在硬件系统的 CPU 上执行,而是由 JVM 执行。JVM屏蔽了与具体平台相关的信息,使Java语言编译程序只须要生成在JVM上运行的目标字节码(.class),知足了高级语言要求的可移植性、可传输性、预编译等等需求。java
一、以 Java 为例,咱们在文本编译器写好了 Java 代码,交由「编译器」编译成 Java Bytecode。而后 Bytecode 交由 JVM 来执行,这时候 JVM 充当了「解释器」的角色,在解释 Bytecode 成 Machine Code 的同时执行它,返回结果。 二、以 BASIC 语言(早期的能够由计算机直译的语言)为例,经过文本编译器编写好,不用经历「编译」的过程,就能够直接交由操做系统内部来进行「解释」而后执行。 三、以 C 语言为例,咱们在文本编译器编写好源代码,而后运行 gcc hello.c 编译出 hello.out 文件,该文件由一系列的机器指令组成的机器码,能够直接交由硬件来执行。
bootstrap
jvm.cfg
-server KNOWN
-client IGNORE
-hotspot ALIASED_TO -server
-classic WARN
-native ERROR
-green ERROR后端
KNOWN 表示存在 、IGNORE 表示不存在 、ALIASED_TO 表示给别的JVM去一个别名 WARN 表示不存在时找一个替代 、ERROR 表示不存在抛出异常性能优化
目前有不少语言选择了jvm,好比说Scala,Kotlin,Ceylon,Xtend,Groovy,Clojure;
JVM通过长期的发展,已经足够成熟和完备。一个完整的语言包括 前端、优化、后端、runtime、库 JVM 把后面四个都给包办了。数据结构
在Java虚拟机的规范中定义了一系列的子系统、内存区域、数据类型和使用指南。这些组件构成了Java虚拟机的内部结构,他们不只仅为Java虚拟机的实现提供了清晰的内部结构,更是严格规定了Java虚拟机实现的外部行为。架构
类加载器子系统:每个Java虚拟机都由一个类加载器子系统(class loader subsystem),负责加载程序中的类型(类和接口),并赋予惟一的名字。每个Java虚拟机都有一个执行引擎(execution engine)负责执行被加载类中包含的指令。jvm
程序的执行须要必定的内存空间,如字节码、被加载类的其余额外信息、程序中的对象、方法的参数、返回值、本地变量、处理的中间变量等等。Java虚拟机将 这些信息通通保存在数据区data areas中。虽然每一个Java虚拟机的实现中都包含数据区,可是Java虚拟机规范对数据区的规定却很是的抽象。许多结构上的细节部分都留给了 Java虚拟机实现者本身发挥。不一样Java虚拟机实现上的内存结构千差万别。一部分实现可能占用不少内存,而其余如下可能只占用不多的内存;一些实现可 能会使用虚拟内存,而其余的则不使用。这种比较精炼的Java虚拟机内存规约,可使得Java虚拟机能够在普遍的平台上被实现。工具
数据区中的一部分是整个程序共有,其余部分被单独的线程控制。每个Java虚拟机都包含方法区(method area)和堆(heap),他们都被整个程序共享。Java虚拟机加载并解析一个类之后,将从类文件中解析出来的信息保存与方法区中。程序执行时建立的 对象都保存在堆中。 当一个线程被建立时,会被分配只属于他本身的PC寄存器“pc register”(程序计数器)和Java堆栈(Java stack)。当线程不掉用本地方法时,PC寄存器中保存线程执行的下一条指令。Java堆栈保存了一个线程调用方法时的状态,包括本地变量、调用方法的 参数、返回值、处理的中间变量。调用本地方法时的状态保存在本地方法堆栈中(native method stacks),可能再寄存器或者其余非平台独立的内存中。性能
Java堆栈有堆栈块(stack frames (or frames))组成。堆栈块包含Java方法调用的状态。当一个线程调用一个方法时,Java虚拟机会将一个新的块压到Java堆栈中,当这个方法运行结束时,Java虚拟机会将对应的块弹出并抛弃。
Java虚拟机不使用寄存器保存计算的中间结果,而是用Java堆栈在存放中间结果。这是的Java虚拟机的指令更紧凑,也更容易在一个没有寄存器的设备上实现Java虚拟机。
解释器咱们能够理解为,把一种高级语言转换成另外一种语言的程序。在JVM中,解释器即将字节码文件转成机器二进制语言,使咱们的电脑能够直接执行。然而由于每次运行程序时都要先转成另外一种语言再做运行,所以解释器的运行速度可想而知,这也形成了java运行速度比较慢的印象。
从本质上讲,每一个程序都是一台机器的“描述”,而解释器就是在“模拟”这台机器的运转,也就是在进行“计算”。因此从某种意义上讲,解释器就是计算的本质
解释器通常都是“递归程序”。之因此是递归的缘由,在于它处理的数据结构(程序)自己是“递归定义”的结构。
在java1.2版本以后,现在的HotSpot VM中不只内置有解释器,还内置有先进的JIT(Just In Time Compiler)编译器,在Java虚拟机运行时,解释器和即时编译器可以相互协做,各自取长补短
HotSpot虚拟机采用了热点代码探测技术:经过计数器找出最具编译价值的代码,通知JIT以方法为单位进行编译。若是方法被频繁调用,则触发标准编译;若是方法中循环次数不少,触发栈上替换编译动做。 HotSpot无需等待本地代码输出后才能执行程序,使得即时编译压力减少,有助于采用更更多的代码优化技术。输出高质量的操做系统本地代码。
为何HotSpot虚拟机要使用解释器与编译器并存的架构?
尽管并非全部的Java虚拟机都采用解释器与编译器并存的架构,但许多主流的商用虚拟机(如HotSpot),都同时包含解释器和编译器。解释器与编译器二者各有优点:当程序须要迅速启动和执行的时候,解释器能够首先发挥做用,省去编译的时间,当即执行。在程序运行后,随着时间的推移,编译器逐渐发挥做用,把愈来愈多的代码编译成本地代码以后,能够获取更高的执行效率。当程序运行环境中内存资源限制较大(如部分嵌入式系统中),可使用解释器执行节约内存,反之可使用编译执行来提高效率。此外,若是编译后出现“罕见陷阱”,能够经过逆优化退回到解释执行。
编译的时间开销
解释器的执行,抽象的看是这样的:
输入的代码 -> [ 解释器 解释执行 ] -> 执行结果
而要JIT编译而后再执行的话,抽象的看则是:
输入的代码 -> [ 编译器 编译 ] -> 编译后的代码 -> [ 执行 ] -> 执行结果
说JIT比解释快,其实说的是“执行编译后的代码”比“解释器解释执行”要快,并非说“编译”这个动做比“解释”这个动做快。 JIT编译再怎么快,至少也比解释执行一次略慢一些,而要获得最后的执行结果还得再通过一个“执行编译后的代码”的过程。 因此,对“只执行一次”的代码而言,解释执行其实老是比JIT编译执行要快。 怎么算是“只执行一次的代码”呢?粗略说,下面两个条件同时知足时就是严格的“只执行一次”
一、只被调用一次,例如类的构造器(class initializer,())
二、没有循环
对只执行一次的代码作JIT编译再执行,能够说是得不偿失。 对只执行少许次数的代码,JIT编译带来的执行速度的提高也未必能抵消掉最初编译带来的开销。
只有对频繁执行的代码,JIT编译才能保证有正面的收益。 编译的空间开销 对通常的Java方法而言,编译后代码的大小相对于字节码的大小,膨胀比达到10x是很正常的。同上面说的时间开销同样,这里的空间开销也是,只有对执行频繁的代码才值得编译,若是把全部代码都编译则会显著增长代码所占空间,致使“代码爆炸”。 这也就解释了为何有些JVM会选择不老是作JIT编译,而是选择用解释器+JIT编译器的混合执行引擎。
为什么HotSpot虚拟机要实现两个不一样的即时编译器?
HotSpot虚拟机中内置了两个即时编译器:Client Complier和Server Complier,简称为C一、C2编译器,分别用在客户端和服务端。目前主流的HotSpot虚拟机中默认是采用解释器与其中一个编译器直接配合的方式工做。程序使用哪一个编译器,取决于虚拟机运行的模式。HotSpot虚拟机会根据自身版本与宿主机器的硬件性能自动选择运行模式。
用Client Complier获取更高的编译速度,用Server Complier 来获取更好的编译质量。为何提供多个即时编译器与为何提供多个垃圾收集器相似,都是为了适应不一样的应用场景。
开发人员能够经过以下命令显式指定Java虚拟机在运行时到底使用哪种即时编译器,以下所示:
-client:指定Java虚拟机运行在Client模式下,并使用C1编译器;
-server:指定Java虚拟机运行在Server模式下,并使用C2编译器。
复制代码
wiki上总结的jvm产品 https://en.wikipedia.org/wiki/Comparison_of_Java_virtual_machines
字节码转义后能够容易的看出,是如何加载了init方法和add方法。
iload_1 从局部变量0中装载int类型值
iload_2 从局部变量0中装载int类型值
iadd 执行int类型的加法
ireturn 从方法中返回int类型的数据
复制代码
一、[讨论] [HotSpot VM] JIT编译以及执行native http://hllvm.group.iteye.com/group/topic/39806
二、JVM编译器的编译过程 http://blog.csdn.net/tingfeng96/article/details/52261219
三、JVM即时编译(JIT) http://blog.csdn.net/sunxianghuang/article/details/52094859