Hotspot 性能架构 -转

ぐ巨炮叔叔 提交于 2019-11-29 00:28:06
第一章:介绍和概述

Java HotSpot虚拟机是Sun公司的Java平台一个高效的虚拟机实现。Java HotSpot技术提供Java标准平台的基础设施,提供对快速开发、部署关键业务的桌面和企业应用程序的解决方案。Java SE可应用在Solaris操作环境、Linux和Windows下,也可以应用在其它通过Java技术认证的平台下。




Java平台已经成为软件开发和部署的主流工具。拥有成千上万的开发者和用户,java平台在如下许多方面增长迅速:从信用卡到无线设备,从桌面机到大型机。Java平台是部署网页Applet、Web服务、大型商业程序等应用的基础设施。

Java HotSpot构建在Java技术跨平台和健壮的安全模型之上,并具备可扩展性、质量和性能方面的新特性。除了这些新特性之外,该版本的HotSpot是向上兼容的。

Java HotSpot几乎全面支持企业应用的开发、部署和管理,它被用在:
  • 集成开发环境(IDE),如Sun Java Studio工具、NetBeans开源项目、IBM的Eclipse,Oracle JDeveloper等等。
  • 应用服务提供者,如Sun Java系统应用服务器、BEA系统WebLogic软件、IBM WebSphere软件,Apple电脑的WebObjects软件等等。

Sun Microsystems, Inc.下致力于通过使用各种各样的工具标准和内部开发的标准来改善性能。客户和服务端Java虚拟机环境都能从这些性能的改善中获益。

Java标准平台包括Java虚拟机的两个实现:

  • Java HotSpot客户端虚拟机,当在客户环境中通过减少应用启动时间和内存占用它被调优至最佳性能。
  • Java HotSpot服务端虚拟机,当运行在服务器环境中时,它被设计为以最快的速度运行。

 

Java HotSpot虚拟机 -- 构建在坚实的基础之上


Java HotSpot虚拟机构建在拥有许多特性和能力的坚实基础之上。支持动态、面向对象优化的架构使其具有世界级的性能。通过虚拟机支持的多线程使得即使在当今最大的计算机系统中也能获得很高的可扩展性。高度的可靠性(Reliability)、可用性(Availability)和可服务性(Serviceability)提供了企业级的可可靠性,也使其具备 快速开发、自省和可管理的能力


第二章:Java HotSpot虚拟机架构概述

Java HotSpot虚拟机是Sun的Java平台虚拟机。通过联合使用最新的内存模型,垃圾收集,和自适应优化多种先进的技术,它为Java应用程序提供了最佳性能。以下用高屋建瓴(high-level)和面向对象的风格对Java HotSpot的特点进行描述:

  • 统一的对象模型
  • 解释、汇编、和本地的桢使用相同的堆栈
  • 基于本地线程的抢占式多线程技术
  • 精确的代压缩垃圾收集
  • 超级快速( Ultra-fast )的线程同步
  • 动态解优化(deoptimization)和积极( aggressive) 编译优化
  • 虚拟机启动时根据不同的系统产生相应的运行程序
  • 支持并行编译的编译器接口
  • 运行时性能检测仅集中于对“热”方法的编译

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虚拟机采用先进的代拷贝收集器,它提供如下两点好处:

  • 相比较非代(nongenerational)收集器,对大多数程序它提高分配速度和总体垃圾收集效率。
  • 相应地也减少由于垃圾回收造成用户可觉察的暂停的次数和时间。

代收集器利用了这样一个事实,即在大多数的程式,大多数对象(通常大于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位虚拟机它也提供了一定的好处。

比如:

Java代码

 

  1. <SPAN style="FONT-SIZE: small">public class Button {   
  2.   char shape;   
  3.   String label;   
  4.   int xposition;   
  5.   int yposition;   
  6.   char color;   
  7.   int joe;   
  8.   object mike;   
  9.   char armed;   
  10. }</SPAN>  
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位虚拟机需要四个字节对齐到指针边界)。现在,对象字段将被重新排序成这样:

Java代码

 

  1. <SPAN style="FONT-SIZE: small">...   
  2.   object mike;   
  3.   int joe;   
  4.   char color;   
  5.   char armed;   
  6. ...</SPAN>  
...   object mike;   int joe;   char color;   char armed; ...


这样便不会有任何空间浪费了。

 

 


第三章:Java HotSpot编译器

概述

为提高Java程序性能,很多尝试集中那些为传统语言开发的编译技术。JIT编译器就是一个快速的传统编译器,它在运行期间翻译Java字节码成本地机器码。运行在终端用户机器上的JIT实际执行字节码并在每个方法第一次执行时编译。

但是JIT编译器也存在某些问题。首先,因为编译器运行占用用户时间,因此它严重受制于编译速度:如果编译速度不是非常快,那么用户将在启动程序或程序的某部分察觉到重大延迟。它也使得很难执行高级优化技术,因为这通常会严重降低编译性能。

其次,即使JIT有时间执行全面优化,对Java语言来说这种优化也不如像C、C++的传统语言那么有效。造成这种情况有很多原因:

  • Java语言是动态安全的,这意味着它确保程序不会违反语言语义或访问非结构化内存。这意味必须频繁动态测试(当向下转型和对对象数组进行排序时)。
  • Java语言在堆中分配所有对象,不像C++,它在栈中分配许多对象。这意味着Java中的对象分配频率要远远高于C++中的对象分配频率。另外,因为Java语言带垃圾回收,它同C++有着非常不同类型的内存分配开销(包括潜在的搜寻可用空间和写屏障(write-barrier)开销)。
  • Java语言的大多数方法调用是虚拟的(潜在的多态),它们比在C++语言中被更频繁的使用。这不仅意味着方法调用性能占据更支配的地位,同时也意味着静态编译优化器(尤其是内联那样的全局优化)更难处理方法调用。许多传统优化在方法调用之间最为有效,这类优化在Java语言中变得不那么有效。java语言的方法调用之间的距离通常很短,这与它们通常只与小部分的代码工作有关。
  • 由于动态类加载机制Java程序能够在运行时改变行为。这使得更加难以做许多种类的全局优化。编译器需要不仅能够检测由于动态加载造成的优化失效,而且需要能够在运行是撤消或重做这些优化,即使它们涉及堆栈中活动方法。这必须在不违反或影响java程序执行语义的情况下完成。


因此,要使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支持一整套高级优化技术,它们即能够优化传统的流线程序也能够优化面向对象的程序。其中的一些优化包括:

  • 深度内联并且内联可能的虚拟方法调用:正如前面描述的那样,客户端和服务端编译器联合使用方法内联、全局分析和动态优化来进行深度内联,这显著减少了方法调用开销。
  • 快速的instanceof/checkcast:Java HotSpot虚拟机和编译器支持一种新型的技术,它加快了Java程序因类型安全而需要频繁执行的类型测试的时间。这进一步减少了面向对象编程的时间消耗。
  • 取消范围检查:Java语言规范要求在每次对数组进行访问时都进行数组边界检查。编译器可以取消边界检查,如果它可以证明数组访问总是在边界以内。
  • 解循环(loop unrolling):服务器端虚拟机有解循环的功能,这是一个标准的编译器优化,它能够使循环执行得更快。解循环增加循环体的大小同时也减少了迭代的次数。解循环也增加其它优化的有效性。
  • 反馈导向优化:服务器端虚拟机在编译Java字节码成优化的机器代码之前会在解释器中执行广泛的性能检测。检测到的数据提供给编译器更多关于使用的数据类型和代码间的热点路径等信息。利用这些信息,在某些条件下编译器能够更加积极乐观地去优化代码。如果运行期间某个假设的属性被违反了,代码会被解优化,以后将会被重新编译和重新优化。

 

第四章:Java HotSpot虚拟机的高级特性

Java HotSpot虚拟机支持许多高级特性,它们促使了高扩展性,高性能和企业级的可靠性,可用性和可服务性。


可扩展性

 

Java HotSpot虚拟机添加自动调整大小和自适应的技术,这被称为人机工程学。目前,人机工程学体现在两个主要领域。首先,根据机器的物理配置(例如,考虑到处理器的数量和可用的物理内存),客户端或服务器虚拟机将被自动被选中。特别是,带有大量处理器和内存的机器将被自动使用服务器端虚拟机,垃圾回收堆的大小也会根据应用硬件的配置被自动设置为合适的值。第二,Java HotSpot虚拟机的垃圾收集算法能够做自我调整,已经不需要明确指定年青和年老代的相对大小。垃圾收集器会自我调整以改善应用的吞吐量,并减少暂停。人体工学技术自动改善服务器端应用的可扩展性,将来的版本在这个领域已经计划要做更多的工作。

 


性能


除了Java HotSpot虚拟机架构提供的核心的面向对象的优化,虚拟机和Java运行环境也支持一些其它的关键性能优化:

  • 快速反射:Java库现在频繁使用方法和构造器之类的反射对象来产生字节码桩。这种技术将反射调用暴露给Java HotSpot编译器,这获得了更高的性能,在某些情况下服务器端的虚拟机能够完全消除反射调用带来的开销。这显著加快了大量使用反射代码的执行速度,比如在序列化、RMI和CORBA的代码环境中。
  • 新I/O优化:Java HotSpot编译器特殊对待在新I/O缓存上的操作,这为get和put方法调用产生高质量的机器代码。得益于新的I/O API,网络和文件I/O中性能和可扩展性已经得到大幅度提升,这些使得Java应用现在已经能够达到可以和C和C++应用相媲美的吞吐量。新的I/O缓存优化也能够应用在其它领域,比如3D图像、在Java平台和外部世界之间传输大量数据。


可靠性,可用性和可服务性

当前版本的Java HotSpot是目前为止最可靠的虚拟机。最近版本的虚拟机创造了企业应用的可靠性和可用性的新纪录。

Java HotSpot虚拟机包含Java虚拟机工作接口的参考实现(Java Virtual Machine Tools Interface, JVM TI)。这允许性能检测、调试和监视器之类的工具去观察和控制JVM。包含的特性有:

  • 全速调试:Java HotSpot虚拟机利用动态解优化技术来支持应用的全速调试。早期版本的Java虚拟机实现,当激活调试时,应用仅会被在解释器中执行。在调试语义中激活Java HotSpot编译器将获得巨大的性能提升,并且在很多情形下可能通过运行调试支持来获得更好的应用可服务性。另外,调试器能够在某种异常被抛出时激活。
  • 执交换(HotSwap)支持:Java HotSpot虚拟机的面向对象架构使得能支持一些高级特性,如运行期间类的重定义或者”热交换“。这个特性使能够通过调试API替代正在运行程序为更改后的代码。热交换为Java平台高度架构提供额外的功能,在调试器的控制下类能够在执行过程中被更新。通过将原方法热交换成性能检测代码被插入后的方法,它能够执行性能检测操作。

Java HotSpot虚拟机中的几个额外特性加快了Java应用程序开发和提高了可服务性。

  • JNI错误检测:通过命令行选项-Xcheck:jni,能够执行JNI检查。在开发过程中打开此选项,使得能够检测在程序部署之前就检测出参数合法性。具体来说,Java HotSpot虚拟机会验证传给JNI函数的参数,也会验证处理JNI请求时运行环境数据。任何遇到的无效数据被认为是本地代码的错误,这时虚拟机将会终止执行。
  • 错误报告。如果JVM检测到本地代码的崩溃,比如开发者写的JNI代码或者虚拟机本身,它将打印和记录关于崩溃的调试信息。错误消息通常报信函数名、库名、源文件名和错误发生的行数。这使得开发者能够容易和有效地高度应用程序。如果错误消息指示是JVM代码的错误,它允许开发者提交一份更精确和有用的bug报告。
  • 信号链设施(Singal-chaining facility)。信号链使Java平台能够更好地与安装了信号处理器的本地代码进行互操作。信号链设施可工作在Solaris和Linux平台上。信号链设施的引入是为了以前版本Java HotSpot虚拟机有关信号处理的一个问题。在1.4版本之前,Java HotSpot虚拟机不允许为某些信号安装应用信号处理器,这些信号包括SIGBUS、SIGSEGV或SIGILL,因为这些信号可能与Java HotSpot虚拟机内部使用的信号处理器冲突。


第五章:对软件重用性的影响


概述

 

面向对象编程的一个主要好处是,通过为软件重用提供强大的语言机制,它能够增加开发生产力。在实践中,很少达到这样的软件重用。大量使用这些机制将显著降低程序性能,这导致程序员很少使用它们。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/ 得到下列环境的虚拟机:

  • 针对SPARC平台的Solaris操作环境
  • 针对Intel平台的Solaris操作环境
  • Linux操作系统:针对Intel平台的Red Hat企业Linux的某些版本、SuSE Linux和Sun Java桌面系统。
  • 针对Intel平台的微软操作系统

 


第八章:资源

下面这些网页提供了额外的信息:

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!