Sun Microsystems, Inc.下致力于经过使用各类各样的工具标准和内部开发的标准来改善性能。客户和服务端Java虚拟机环境都能从这些性能的改善中获益。
Java标准平台包括Java虚拟机的两个实现:
html
Java HotSpot虚拟机 -- 构建在坚实的基础之上 前端
Java HotSpot虚拟机构建在拥有许多特性和能力的坚实基础之上。支持动态、面向对象优化的架构使其具备世界级的性能。经过虚拟机支持的多线程使得即便在当今最大的计算机系统中也能得到很高的可扩展性。高度的可靠性(Reliability)、可用性(Availability)和可服务性(Serviceability)提供了企业级的可可靠性,也使其具有 快速开发、自省和可管理的能力 。
第二章:Java HotSpot虚拟机架构概述
Java HotSpot虚拟机是Sun的Java平台虚拟机。经过联合使用最新的内存模型,垃圾收集,和自适应优化多种先进的技术,它为Java应用程序提供了最佳性能。如下用高屋建瓴(high-level)和面向对象的风格对Java HotSpot的特色进行描述:
java
JDK包括两种不一样形式的虚拟机,一个是用在客户端,一个是为服务器应用程序。 这两种虚拟机共享Java HotSpot运行环境的代码基,但因为客户端和服务器端各自不一样的性能特色, Java HotSpot 为其提供了不一样编译器。这些差别包括编译内联规则和堆默认值。
JDK的发布版本中包含两种形式的虚拟机,开发人员能够经过-client或-server选项来选择客户端虚拟机或服务器 端 虚拟机。
服务器端和客户端虚拟机很类似,为尽量的提供高峰运行速度,服务器端虚拟机已做了专门优化。它是专为执行长时间运行的服务器应用程序的,这种程序须要尽量快的运行,而不是须要启动快或小的内存占用。
客户端虚拟机的编译器是之前版本JDK所使用的经典(classic)虚拟机和即时(JIT)编译器的升级。客户端虚拟机提升了应用程序和Applets的运行性能。Java HotSpot客户端虚拟机为减小应用程序的启动时间和内存占用做了优化,这使得它特别适合于客户端环境。通常来讲,GUI特别适合使用客户端虚拟机。
服务器端虚拟机编译器执行的许多复杂优化,客户端虚拟机的编译器并不会执行,但与此同时,分析和编译代码块的时间便会减小。这意味着客户端虚拟机能够启动得更快和占用更少的内存。
服务器端虚拟机包含了一种先进的自适应编译器,它支持许多和C++编译器支持的相同类型的优化,以及一些传统编译器所不能作的优化,如虚拟方法调用间的积极内联(aggressive inlining)。与于静态编译器相比,自适应编译器在这方面有着无可比拟的竞争优点。自适应优化技术在作法上是很是灵活的,典型状况下甚至优于先进的静态分析和编译技术。
这两种形式的虚拟机提供了很是可靠、安全、和可维护的环境,以知足当今企业客户的须要。
图左边的是Java HotSpot客户端虚拟机,右边的是Java HotSpot服务器端虚拟机,它们使用不一样的编译器,可是使用相同的虚拟机接口,使用相同的垃圾回收程序、解释器、线程和锁子系统等等。
内存模型:没有句柄对象 (Memory Mode Handless Objects)
在之前版本的Java虚拟机上,如经典虚拟机,使用间接句柄表明对象引用。这使得在垃圾回收过程当中的从新定位对象更容易(注:在垃圾回收过程当中对象的地址会改变),但存在明显的性能瓶颈,由于对Java编程语言的对象访问须要两次间接访问(注:首先访问间接句柄,而后访问实际的对象)。
Java HotSpot虚拟机中没有使用间接句柄。对象引用就是直接指针。这使得访问实例变量像在C语言中同样快。当在内存回收过程当中对象被从新分配时,垃圾回收器是负责寻找和在适当位置更新全部对象引用。
两个字(Word)的对象头
Java HotSpot虚拟机采用了两个字的对象头,而不是像经典虚拟机中那样使用三个字。因为Java对象平均大小很小,这对空间消耗有重大影响,在典型的应用程序中,它能节省8%大小的堆空间。第一个字包含标识对象身份的哈希代码和GC状态等信息。第二个字是对对象所在类的引用。只有数组有第三个字,它是数组的大小。
反射数据也是对象
类、方法及其余内部反射数据直接表现为堆上的对象(虽然这些对象可能没法在基于Java的程序中直接得到)。这不只简化了虚拟机的内部对象模型,也使得类也能够被垃圾回收器回收。
本地线程支持,包括对抢占线程和多处理器的支持 程序员
Per-thread method activation stacks are represented using the host operating system's stack and thread model.每线程方法的激活栈使用主机操做系统的堆栈和线程模型。Java语言的方法和本地(native)方法共享相同的堆栈,这使得C和Java之间的方法调用很是快速。Java使用主机做业系统的线程调度机制提供对抢占线程的支持。
使用本地操做系统线程和调度一个主要的优点是有可以充分利用本地操做系统对多处理器的支持。由于在执行Java程序时,Java HotSpot虚拟机并不知道因为线程抢占和多处理器所形成的竞争条件,Java线程会自动利用本地操做系统提供的任何线程调度和处理器分配规则。
垃圾回收
Java HotSpot内存系统本质上是着基于代的,这为使用特定垃圾回收算法提供了灵活性,用来知足不一样应用的要求。Java HotSpot虚拟机支持几种不一样的垃圾收集算法,用于知足不一样的暂停时间和吞吐量的要求。
背景
Java对程序员的一个主要的吸引力是由于它是第一个提供内置自动内存管理,或垃圾收集(GC)的主流编程语言。传统语言使用明确分配/释放模型来动态内存分配。在实践中,这不只是内存泄漏,程序错误及程序崩溃的重大来源,也是一个性能瓶颈和一个代码模块化和重用的主要障碍 (没有模块间明确的和难以理解的协做,决定跨模块的内存释放点几乎是不可能的) 。在Java中,垃圾收集也是“安全”执行语义中一个重要部分。 算法
垃圾回收器在幕后自动释放未使用对象所占用的内存。这彻底消除了因为释放太少所形成的内存泄漏,以及释放太多所形成的程序崩溃和难以发现的引用错误。
传统的收集垃圾一直被视为低效的过程,相对于明确释放模型,它阻碍了性能。事实上,现代垃圾回收技术性能已经有很大的提升,以至于垃圾回收的总体性能已经大大优于明确释放模型的性能。
Java HotSpot的垃圾 收集
除包括下述优秀的特性,内存系统被设计成一个干净的,面向对象的框架,它能够很容易被度量(instrumented),实验,或扩展使用新的垃圾收集算法。
Java HotSpot垃圾收集的主要特色介绍以下。总的来讲,这些特色对如下两类程序都是很是适合的:一类是须要尽量高的性能的应用程序,另外一类是须要长时间运行的应用程序,而且它不能容忍内存泄露和因为内存碎片形成的内存不足。 数据库
精确性 编程
Java HotSpot的垃圾 收集 器是一个彻底精确的 收集 器。相比之下,其余许多垃圾收集是至关保守或部分准确。保守的垃圾收集能够颇有吸引力,由于它是很容易添加到没有垃圾收集的系统,它也有某些弊端。一般,保守的垃圾收集容易形成内存泄漏,不容许对象迁移并可能致使堆碎片。
保守收集器不肯定全部对象引用的位置。所以,保守收集器必须假设看起来是对象引用的内存字(word)就是一个对象引用。这意味着它会犯错误,如可能将一个整数误认为为对象引用。看起来像指针的内存单元被认为就是对象引用,这致使GC变得不精确。这有几个负面影响。第一,当这些错误发生时(在实践中不是很常常) ,内存泄漏以难以预料的方式发生,并且几乎不可能被程序员重现或调试。第二,由于它有可能犯了一个错误,保守收集器必须使用间接指向对象的句柄,这下降了性能,或者避免从新分配对象,由于从新分配对象须要更新全部对象引用。若是收集器不肯定一个可能的引用是否为一个真正的引用,这是不可能作到的。没法从新分配对象会致使内存碎片,更重要的是,它不能使用先进的代拷贝收集算法。
由于Java HotSpot收集器是彻底精确的,它能够做出保守收集器不能做出的强大设计保证:
后端
精确的垃圾收集机制避免了意外的内存泄漏,可以使对象从新分配,并提供充分的堆压缩。Java HotSpot虚拟机的GC机制即便对于大型堆(heap)也表现很好。 数组
代拷贝收集(Genrational Copying Collection) 缓存
Java HotSpot虚拟机采用先进的代拷贝收集器,它提供以下两点好处:
代收集器利用了这样一个事实,即在大多数的程式,大多数对象(一般大于95%)很短命(例如,它们被用做临时数据结构)。经过分配建立的物体分配到一个单独的对象区,代收集器能够完成几件事。第一,由于新对象像栈同样被连续分配在对象区,分配变得很是快,由于它只是涉及更新单个指针和执行一个对象区溢出检查。其次,当对象区溢出时,大部分在对象区的对象已经死亡,垃圾 收集 器只是简单地移动几个幸存对象到其它地方,并不须要对象区已经死亡的对象作任何收集工做。
并行年轻代收集器(Parallel Young Generation Collector)
上述的单线程拷贝收集适合许多部署,但当扩展应用程序以利用多处理器时,这可能会成为一个瓶颈。为了充分利用多处理器机器全部可用CPU,Java HotSpot虚拟机提供一个可选的对年轻代的多线程收集器,跟踪和拷贝幸存的对象是由并行的多线程同步完成。实现被仔细调整,它可以均衡可用处理器的收集工做,让收集器可扩充到大量处理器。这下降了收集年轻代空间的暂停时间,而且最大化垃圾 收集 的吞吐量。并行收集器已经在超过100个CPU和0.5TB堆空间的系统上作过测试。服务器端虚拟机默认使用并行年轻代收集器算法。
当移动对象时,并行收集器尽可能使相关的对象在一块儿,从而提升了内存可定位性和缓存利用率,并提升性能。这是经过以深度优先顺序拷贝对象来完成的。
并行收集器也会优化内存的使用。它并不须要预留部分旧对象空间以保证拷贝全部幸存对象的所需的空间。相反,它使用一种新的预测技术来拷贝对象。若是旧对象空间很稀少,这一技术可让收集器平滑地过分到压缩堆,而不须要预留任何空间。这使得可以更好地利用可用堆空间。
最后,并行收集器是可以动态调整一些参数,这会改善许多应用和环境中的垃圾收集的性能。这意味须要较少的用户手工调整。这种能力在并行收集器中被首次引入,如今也应用在许多其余垃圾收集算法中。
要与默认的单线程收集器的性能至关,并行收集器须要2-4个CPU,这取决于平台和应用。这种状况预计在将来的版本中会有所改善。
标记紧凑旧对象收集器(Mark-Compact Old Object Collector)
尽管代拷贝收集器有效的收集大多数死亡对象,可是年长对象仍然在旧对象内存区中积累。 偶然地,由于低内存或程序请求,必须执行对旧对象的垃圾收集。Java HotSpot虚拟机默认使用标准标记紧凑收集算法,该算法从根开始遍历整个存活对象图,而后压缩死亡对象留下的的空间。经过压缩堆中空白,而不是将收集成一个链表,这减小了内存碎片同时使对象分配更有效率,由于这不须要对链表进行扫描。
多数标记紧凑对象收集器(Mostly Concurrent Mark-Sweep Collector)
若是应用须要很大的堆(heap),默认的旧代标记紧凑垃圾收集形成的暂停每每形成干扰,由于应用线程暂停的时间与堆的大小成正比。Java HotSpot虚拟机实现了一个可选的并行旧对象收集器,它利用了处理器的空闲周期来收集大堆 (heap) ,从而仅暂停线程很短的时间。这是经过在应用线程执行时作大量的跟踪和清除工做来实现的。在某些状况下,繁忙应用的吞吐量会有小幅降低,由于并行收集活动占用了一些处理器周期;可是,平均和最坏状况下的垃圾收集停顿时间,每每会减小了一到两个数量级于是容许更平滑的应用响应,而不存在默认标记紧凑对象收集器运行在大型堆上时的忽然停顿。
并行旧代收集器(Parallel Old Generation Collector)
当前版本的Java HotSport虚拟机引入了一种并行标记旧代收集器,旨在提升须要大型堆 (heap) 的应用的可扩展性。而并行标记-清除收集器集中于减小暂停时间,并行旧代收集器集中于经过并发线程收集旧对象来增长吞吐量。并行旧代收集器使用许多新技术和内部数据结构,以实现高扩展性。
更多信息
了解更多关于Java HotSpot支持的垃圾收集算法,请参阅内存体管理白皮书 。
超级快速 的线程同步
Java语言容许程序并行执行--线程。Java提供语言级的线程同步,这使得书写带细粒度锁的多线程程序变得很是容易。相比较于Java语言的其它微操做,之前版本的Java虚拟机如经典虚拟机的同步实现显得很是低效,这使得细粒度同步成为程序性能的一个主要瓶颈。
Java HotSpot虚拟机对非竞争性的和竞争性的同步采用了领先的技术,这使得同步操做的性能有了至关大的提高。非竞争性的同步操做,这占同步操做的多数,被实现得很是快,仅仅是常量的时间。加上最新的优化,即便在多处理器计算机上这些同步操做在最好状况下也几乎是没有代价的。竞争性的同步操做使用了先进的自适应旋转(spinning)技术,这使得即便对存在至关多锁竞争的应用程序也能提升程序的吞吐量。所以,同步操做已经变得如此之快以致于对现实世界中的大多数程序来讲同步操做已经再也不是一个性能问题。
64位架构
早期的Java HotSpot虚拟机仅能寻址4G的内存空间,即便对于如Solairs OE这样64位操做系统也是如此。尽管4G的内存对桌面系统是足够的,可是如今的服务器一般会包含远远超过4G的内存。好比,Sun Fire E25K服务器支持超过1.15T的内存。随着64位JVM的到来,基于Java的应用已经可以充分利用这些系统的所有内存。
有几类应用使用64位寻址颇有用。好比那些在内存中存储大量数据的应用。如今应用可以避免数据从磁盘中分页或从关系数据库中提取数据的开销。这会大幅度提高这类应用程序的性能。
Java HotSpot虚拟机如今是64位安全的,服务器端虚拟机同时支持32位和64位的操做。用户能够经过命令行参数-d32和-d64来分别选择32位或64位的操做。为运行在64位虚拟机上,使用Java本地接口的用户须要从新编译他们的代码。
对象打包
对象打包已经被添加进来,它的目的是为了尽量的减小不一样大小数据类型之间的空间浪费。这对64位环境很是有用,可是对32位虚拟机它也提供了必定的好处。
好比:
public class Button { char shape; String label; int xposition; int yposition; char color; int joe; object mike; char armed; }
clolor和joe之间存在空间浪费(须要三个字节以对齐到int的边界),joe和mike之间也存在空间浪费(对64位虚拟机须要四个字节对齐到指针边界)。如今,对象字段将被从新排序成这样:
... object mike; int joe; char color; char armed; ...
这样便不会有任何空间浪费了。
第三章:Java HotSpot编译器
概述
为提升Java程序性能,不少尝试集中那些为传统语言开发的编译技术。JIT编译器就是一个快速的传统编译器,它在运行期间翻译Java字节码成本地机器码。运行在终端用户机器上的JIT实际执行字节码并在每一个方法第一次执行时编译。
可是JIT编译器也存在某些问题。首先,由于编译器运行占用用户时间,所以它严重受制于编译速度:若是编译速度不是很是快,那么用户将在启动程序或程序的某部分察觉到重大延迟。它也使得很难执行高级优化技术,由于这一般会严重下降编译性能。
其次,即便JIT有时间执行全面优化,对Java语言来讲这种优化也不如像C、C++的传统语言那么有效。形成这种状况有不少缘由:
所以,要使Java语言性能获得根本性的改善,必须提供对这些问题的非传统的解决方法,而不是盲目的使用传统的编译技术。
Java HotSpot虚拟机架构经过下述的自适应优化技术解决了Java语言性能问题。
热点检测(HotSpot Detection)
自适应优化利用了一个很是有趣的程序属性来解决JIT编译问题。实际上全部的程序花费大量的时间执行很小一部分代码。 Java HotSpot 虚拟机 没有即时的一个方法一个方法的编译,而解释运行程序,而且分析代码以检测程序的关键热点代码。而后它集中对这些热点代码使用全局本地优化。经过避免编译不多执行的代码(大部分代码都不多执行),Java HotSpot集中主意到程序的性能关键部分,又没有增长整体的编译时间。热点监视在程序运行时动态进行,所以它会在运行时调整性能以知足用户的要求。
这种方式的一个细微但很重要的好处是,经过延迟编译直到代码已经运行了一段时间,代码被使用方式的信息可以被收集起来,而后用于执行一些更加智能的优化。内存占用也会减小。除了收集程序的热点以外,也会收集其它类型的信息,好比虚拟方法调用的调用者-被调用者的关系。
方法内联
Java语言虚拟方法调用的频率成为一个很重要的优化瓶颈。一旦Java HotSpot自适应优化器收集到程序热点,它不只编译这些热点代码成本地代码,并且执行大量的方法内联。
内联有很重要的好处。它急剧减小方法调用的频率,它减小了执行方法调用的时间。更为重要的是,内联产生了更大的代码块能够被优化器利用。这样就大大增长传统编译器优化技术的有效性,同时克服了增长Java语言性能的一个主要障碍。
内联与其它代码优化一块儿使用,由于这使得它们更加高效。随着Java HotSpot编译器的成熟,内联代码块将向更多高级优化敞开大门。
动态解优化(Dynamic Deoptimization)
尽管上部分描述的内联是一个很重要的优化技术,可是它传统上一直难以使用在像Java这样的动态面向对象语言上。尽管检测热点和调用的内联方法已经足够复杂,可是它并不能知足所有Java编程语言的语义。这是由于Java程序不只可以在运行期间改变方法调用的模式,并且也能在运行期间动态加载新的Java代码。
内联基于全局分析。动态加载显著地更加了内联的复杂度,由于它改变了程序的全局关系。一个新的类可能包含须要在某个地方被内联的新方法。所以Java HotSpot必须可以动态解优化(而且从新优化,若是必需)先前优化的热点代码,即便在正在执行热点代码。没有这种能力,通常的内联不能安全的用在Java程序中。
Java HotSpot客户端和服务器端编译器都充分支持动态解优化。这使得积极乐观优化(aggressive and optimistic optimization)和其它优化技术如全速调试(full-speed debugging)成为可能。
Java HotSpot客户端编译器
Java HotSpot客户端编译器是一个简单快速的三阶段编译器。在第一个阶段,一个平台独立的前端构造字节码的一个高级中间代码(high-level intermediate representaion, HIR)。HIR使用静态单分配(static single assignment, SSA)形式来表明代码值,这是为了使发生在IR构造期间和以后的一些优化更容易。在第二个阶段,平台特定后端从HIR产生低级中间代码(low-level intermediate representation, LIR)。最后的阶段使用自定义的线性扫描算法在LIR上分配寄存器,在LIR上作窥孔(peephole)优化,而后从HIR中产生机器代码。
重点被放在从字节码中提取和保存尽量多的信息。客户端编译器集中在局部代码质量,它不多作全局优化,由于这会消耗不少编译时间。
Java HotSpot服务器端编译器
服务器端编译器为典型的服务器应用的性能配置作过调整。Java HotSpot服务器端编译器是一个高级充分优化编译器。它采用了一种先进的基于静态单分配(SSA)的IR作优化。优化器执行全部的经典的优化,包括清除死代码,提出循环不变式,消除共同子表达式,常量传播,将全局值数字化,全局代码移动。它还采用和Java技术更密切的优化技术,如空值检查和范围检查,异常抛出路径的消除和优化。寄存分配器是一个全局图着色分配器,它充分利用广泛使用在RISC徽处理器上的大寄存器集合。编译器是高度可移植的,它依靠机器描述文件来目标硬件各方面的特征。以JIT的标准来看,编译器是缓慢的,但它的速度仍然远远超过传统的优化编译器,代码质量的提升 减小了执行时间 ,从而抵消了额外的编译时间 。
编译优化
Java HotSpot支持一整套高级优化技术,它们即可以优化传统的流线程序也可以优化面向对象的程序。其中的一些优化包括:
第四章:Java HotSpot虚拟机的高级特性
Java HotSpot虚拟机支持许多高级特性,它们促使了高扩展性,高性能和企业级的可靠性,可用性和可服务性。
可扩展性
Java HotSpot虚拟机添加自动调整大小和自适应的技术,这被称为人机工程学。目前,人机工程学体如今两个主要领域。首先,根据机器的物理配置(例如,考虑处处理器的数量和可用的物理内存),客户端或服务器虚拟机将被自动被选中。特别是,带有大量处理器和内存的机器将被自动使用服务器端虚拟机,垃圾回收堆的大小也会根据应用硬件的配置被自动设置为合适的值。第二,Java HotSpot虚拟机的垃圾收集算法可以作自我调整,已经不须要明确指定年青和年老代的相对大小。垃圾收集器会自我调整以改善应用的吞吐量,并减小暂停。人体工学技术自动改善服务器端应用的可扩展性,未来的版本在这个领域已经计划要作更多的工做。
性能
除了Java HotSpot虚拟机架构提供的核心的面向对象的优化,虚拟机和Java运行环境也支持一些其它的关键性能优化:
可靠性,可用性和可服务性
当前版本的Java HotSpot是目前为止最可靠的虚拟机。最近版本的虚拟机创造了企业应用的可靠性和可用性的新纪录。
Java HotSpot虚拟机包含Java虚拟机工做接口的参考实现(Java Virtual Machine Tools Interface, JVM TI)。这容许性能检测、调试和监视器之类的工具去观察和控制JVM。包含的特性有:
Java HotSpot虚拟机中的几个额外特性加快了Java应用程序开发和提升了可服务性。
第五章:对软件重用性的影响
概述
面向对象编程的一个主要好处是,经过为软件重用提供强大的语言机制,它可以增长开发生产力。在实践中,不多达到这样的软件重用。大量使用这些机制将显著下降程序性能,这致使程序员不多使用它们。Java HotSpot技术的一个使人惊奇的副效应就是它显著下降了性能损失。Sun相信,经过第一次就充分利用面向对象的重用机制,而不向软件性能做妥协,这将彻底影响面向对象软件开发的方式。
很容易举出这方面的例子。一份对Java程序员的调查显示许多程序员避免充分地使用虚拟方法(一般也书写很大的方法),由于他们认为虚拟方法调用将致使严重的性能惩罚。使用处处存在的细粒度虚拟方法,好比Java语言中那些非静态或非final的方法,对构造高度重用的类是极其重要的,由于这些方法充当了一个钩子,容许被子类覆盖父类的行为。
由于Java HotSpot虚拟机内联许多虚拟方法调用,这种性能惩罚已经戏剧性地减小了,在许多状况下甚至是彻底抵消了。
对这个效应的重要性再怎么估计也不算过份。它有可能从根本上改变面向对象代码书写的方式,由于它极大的改变使用重要重用机制的性能平衡。另外,面向对象技术已经成熟,这已经变得很清楚。如今已经变得愈来愈倾向使用细粒度的对象和方法。这个趋势明确无误地代表将来的代码风格将使用更多的虚拟方法。随着更高层的代码风格变得流行,Java HotSpot技术的优势将变得更加明显。
第六章:总结
Java HotSpot虚拟机为Java应用提供了最佳的性能,它提供了高级优化、垃圾回收和线程同步。另外,为了提升Java程序的可靠性、可用性和可服务性,虚拟机也提供调试能力。Java HotSpot虚拟机为客户环境和服务器环境提供了单独的编译器,这使得应用可以根据目标部署环境获得最优性能。经过64位的Java HotSpot的服务器端编译器,可扩展性有了极大的提升。
使用Java HotSpot虚拟机,客户应用程序可以启动得更快、打败更小内存,而服务器程序在长期运行中可以得到更好的性能。两种解决方案都提供了极其可靠、安全和可维护的环境来知足当今企业用户的需求。
第七章:可用性
Java HotSpot虚拟机被包含在Java标准平台环境里。能够从http://java.sun.com/ 获得下列环境的虚拟机:
第八章:资源
下面这些网页提供了额外的信息: