JVM之走进Java(一)

1、Java特点
不仅是一门编程语言,还是有一系列计算机软件和规范形成的技术体系;除了是一门结构严谨、面向对象的编程语言之外:
(1)、跨平台:一次编写,到处运行,主要是java采用中间体(字节码),而非是依赖平台的机器码,并且是在运行时编译;
(2)、相对安全的内存管理和访问机制,避免了绝大多数内存泄漏和指针越界问题;
(3)、实现了热点代码检测和运行时编译优化,可以使Java随着运行时间的增加而获得更高的性能;
(4)、一套完善的应用程序接口,还有无数来自商业机构和开源社区的第三方类库。
2、Java技术体系
JDK:包含Java程序设计语言、Java虚拟机、Java API类库
JRE:Java SE API(Java API子集)、Java虚拟机
Tip:JavaEE是对JavaSE的扩展,这些扩展包一般以javax.作为包名,而java.作为JavaSE核心包,历史原因,一部分的扩展包进入了核心包,因此核心包中也包含了不少javax.*的包名。
3、Java的发展史
Oak(橡树)作为Java语言的前身,在1991年由James Gosling博士领导启动,在1995年随着互联网的兴起,Oak找到自己的定位并蜕变成Java语言,并且在SunWorld大会上Java1.0版本。(JDK1.0)第二年就提供一个纯解释执行的Java虚拟机Sun Classic VM。在1998年发布的JDK1.2中第一次内置了JIT编译器。2004年,发布的JDK1.5(tiger)在语法应用上做了非常大的改进:自动装箱、泛型、动态注解、枚举、可变长参数、遍历循环(foreach)等语法。
4、Java虚拟机的发展史
Sun公司从1996年发布的JDK1.0提供了一个纯解释执行的虚拟机Sun Classic VM,由于相对于C/C++程序执行效率较低,于是在JDK1.2中,Solaris平台上曾出现过一款名为Exact VM的虚拟机,它已经具备现代高性能虚拟机的雏形:两级即时编译器、编译器与解释器混合工作模式、准确式内存管理(即JVM可以知道内存中某个位置的数据具体是什么类型,比如一个数字123456是一个整型数字还是引用的地址),从而抛弃了以前的Classic VM的handler对象查询方式。
但是Exact VM在商业上只存在了很短的时间就被更为优秀的HotSpot VM所取代。HotSpot最初由一个小公司研发,最初也并非为Java语言开发,它继承了Sun之前两款商用虚拟机(当然还有其他很多虚拟机:KVM、Squawk VM、JavaInJava等)的优点,也有自己新的技术优势,比如热点代码探测技术,通过执行计数器找出最具有编译价值的代码,然后通知JIT编译器以方法为单位进行编译,比如方法被频繁调用或方法中有效循环次数很多,将会触发标准编译和OSR(栈上替换),即通过编译器与解释器协同工作,在最优化的程序响应时间与最佳执行性能中取得平衡,而无需等待本地代码输出才能执行程序。
最终经过Sun公司的内部讨论决定采用HotSpot作为Sun公司支持的VM产品。(并不算技术上的胜利)
2009年Oracle了收购Sun公司后加上以前收购的BEA公司,因此oracle拥有目前三大虚拟机的其中两个:JRockit和HotSpot,并宣布把两个优秀的虚拟机取长补短合并为一,且以HotSpot为基础。在2006年的时候Sun公司宣布开源Java并建立了OpenJDK。
BEA JRockit:BEA公司开发一款专门为服务器硬件和服务器端应用场景高度优化的虚拟机,由于专注于服务器端应用,因此不太注重程序启动速度,因此JRockit VM内部不包含解析器实现,全部代码都靠即时编译器编译后执行(即时编译器因该是实时编译源程序为机器码)。
IBM J9 VM:是IBM其中一款并且是主力发展的虚拟机,市场定位与Sun HotSpot接近,从服务端到桌面应用再到嵌入式都全面考虑的多用途虚拟机。
5、HotSpot虚拟机中的即时编译器
HotSpot 虚拟机采用解释器与编译器并存的架构(不是所有的JVM都是这种架构),这也是主流商用虚拟机的架构。
解释器:当程序需要快速启动和执行的时候,解释可以首先发挥作用,省去编译的时间(这里所说的编译时复杂的优化等大范围编译过程,泛指相当于一部分(或全部)源码编译成机器码然后执行),可以一边解释一边执行(转译一行后就执行),但是在优化方面就比较劣势,因此翻译成的机器码可能也比较耗时,即虽然节省了编译的时间,但是却要花费比较多的时间在执行指令上。
编译器:在程序运行后,随着时间的推移,编译器逐渐发挥作用,把越来越多的代码翻译成本地代码(也可能是一种其它的低级语言)之后,存在缓存里,可以获得更高的执行效率。(对比解释器可能编译后执行完当再次执行要重新编译成机器码)
因此:对于运行环境内存资源显示较大(嵌入式系统)可以使用解释执行节约内存。同时解释器还可以组委编译器激进优化的一个“逃生门”,就是编译器根据概率选择一些大多数时候都能提升运行速度的优化手段,当激进的假设不成立,如出现了加载了新类后类型继承结构发生了变化、出现“罕见陷阱”时可以通过逆优化退回到解释状态继续执行。

即时编译器的作用:Java程序在进行解释执行的时候,当虚拟机发现某个方法或代码块(循环体)运行特别频繁时,会把这些代码认定为“”热点代码“(Hot Spot Code),为了提高这些热点代码的执行效率,在运行时把热点代码以方法为对象编译成与本地平台相关的机器码(计算机指令使用特定平台x86、x64、ARM),并进行各层次的优化,完成这个任务的编译器称为即时编译器(区别普通编译器:运行前就把源码编译成特定平台的机器码,同时丧失了可移植性)
Java 执行引擎
这里写图片描述
HotSpot VM内置了两个即时编译器,分别称为Client Compiler(C1)和Server Compiler(C2),1.7以及之前的版本中,默认采用解释器与其中一个编译器直接配合的方式工作,采用哪一个编译器取决于虚拟机的运行模式,HotSpot会根据自身版本和宿主机器的硬件性能自动选择运行模式,用户也可以使用“-client”或“-server”去强制选择。
HotSpot为了在程序启动响应速度与运行效率之间达到最佳平衡,在1.7的server模式虚拟机中启用分层编译的策略作为默认编译策略被开启。
分层编译根据编译器编译优化的规模与耗时,划分不同的编译层次,其中包括:
第0层,程序解释执行,解释器不开启性能监控功能,可触发第1层编译
第1层,已称为C1编译,将字节码编译为本地代码,进行简单、可靠的优化,如有必要,将加入性能监控的逻辑。
第2层(及以上),也称为C2编译,将字节码转换为本地代码,会进行一些耗时较长的优化,甚至会根据性能监控信息进行一些不可靠的激进优化。
分层编译后,C1与C2同时工作,许多代码可能会被编译多次,用C1获得更高的编译速度,C2获得更好的编译质量。
6、HotSpot的热点探测
热点代码主要有两类:被多次调用的方法;被多次执行的循环体;但编译执行对象都是方法。
热点探测技术主要有两种:
(1)、基于采样的热点探测:虚拟机周期性检查各个线程的栈顶,栈顶经常出现的方法就是“热点方法” 简单 高效 还可以获取方法的调用关系,但容易受到线程阻塞和外界因素的影响,很难准备探测方法的热度。
(2)、基于计数器的热点探测:虚拟机为每个方法设置代码块建立计数器,统计执行次数,当超过阈值时,就认为是“热点方法” 。统计结果相对准确严谨,但不能知道方法调用关系。
HotSpot采用第二种方法,不过它为每个方法采用两种计数器:方法调用计数器和回边计数器,每个计数器都有阈值 ,超过就出发JIT编译。

猜你喜欢

转载自blog.csdn.net/qq_26564827/article/details/79860025