java hotspot性能引擎的体系结构
--有关sun的第二代性能技术的白皮书
内容
- 引言
- 概述
- 体系结构
- 内存模型
- 无句柄对象(handleless object)
- 双字对象头
- 将映射数据表示为对象
- 本地线程支持,包括任务抢先和多重处理技术
- 内存垃圾回收
- 背景说明
- java hotspot垃圾回收
- 精确性
- 相继的复制回收
- 采用标记-整理算法的"旧对象"回收器
- 增量"无暂停"垃圾回收器
- 超快速线程同步
- java hotspot编译器
- 背景说明
- "热点(hot spot)"检测
- 方法内嵌
- 动态逆优化
- 优化编译器
- 小结
- 对软件可重用性的影响
- java本地接口(jni)支持
java>tm平台正在成为软件开发和部署的主流载体。在许多领域,java平台的使用率正在迅猛增长--从信用卡到大型计算机、从网页applets到大型商务应用程序。因此,java技术的品质、成熟度和性能就成了对每一个开发人员和用户至关重要的因素。sun microsystems,inc.正在重点投资于能够在许多处理器和操作系统面前"抬起挡路的栏杆"的技术,应用这种技术,软件开发人员可以将基于java的应用程序,在不考虑处理器和操作系统的情况下有效而可靠地运行。
人们对java平台感兴趣的一个主要原因是:基于java技术的程序与用传统语言编写的程序不同,它们是以一种可移植的和安全的形式而分布的。过去,使用可移植的分布形式一般来说都意味着在程序执行中的性能要下降。通过采用现代动态编译技术,这种性能的下降得以减缓,其本质可说是"双收其利"。
举一个简单但很重要的例子:我们可以使一个java技术编译器为特定版本的处理器"在运行中"生成优化的机器码(例如,尽管奔腾和奔腾ii处理器可以运行相同的机器码,但没有一种形式的机器码可以同时对上述二者都是优化的)。于是,java编程语言的字节码分布形式不仅可以提供移植性,而且实际上还可以为性能的提高提供新的机会。
本文将介绍java的第二代性能技术--java hotspot性能引擎。java hotspot性能引擎几乎在其设计的每一个领域都有创新,它使用了广泛的可用来提高性能的技术;这包括可检测并加速性能关键性(performance-critical)代码"在运行中"的适配性优化技术。java hotspot还提供了超快速(ultra-fast)线程同步,以获取线程安全的基于java技术的程序的最大性能;它还提供了垃圾回收器(gc),gc不仅特别快,而且是完全"精确"的(因而也更可靠);另外,采用最新技术的算法也减少或消除了用户对垃圾回收而引起的暂停的感觉。最后,由于java hotspot性能引擎在源代码级是以一种简洁、高级的面向对象的设计风格编写的,因而还进一步改善了维护性和扩展性。
2. 概述
下面是java hotspot性能引擎的主要结构性优势:
1) 更好的一般性能
- 无句柄对象(为提高速度,对象的引用被实现为直接指针);
- 更快的java编程语言的线程同步;
- 为达到更快的c代码的调出和调入,c和java代码可共享相同的激活栈;
- 与及时编译jit相比较,大大减小了代码空间和启动时间总开销。
- 为获得真本地代码性能,优化了本地代码编译器;
- 适配性的"热点(hot spot)"检测主要集中于性能-关键性代码的优化上,从而大大减少了总编译时间和对已编译代码的内存需求;
- 方法内嵌技术为大部分程序消除了大多数动态方法调用;
- 对非内嵌方法的更快的方法调用。
- 更快的对象分配;
- 精确性提供了更准确的对象回收(与保守的(conservative)或半精确的(partially-accurate)那种可引起难以预料的内存泄漏的回收器不同);
- 相继回收对大多数程序来说极大地提高了回收效率;
- 对大多数程序来说, 相继回收还极大地减小了回收"旧的对象"而引起暂停所出现的频率;
- 相继回收也为使用大量"活的(live)"对象的内存的应用程序极大地改善了性能扩展性;
- 使用标记-整理(mark-compact)算法来回收"旧的"对象,消除了内存碎 片,增加了本地性(locality);
- 增量"无暂停"垃圾回收器为"长寿"对象、甚至为极大量的"活"的对象在实质上消除了对象回收过程中出现的用户可视的暂停,这对等待时间敏感的应用程序(如服务器)以及大数据量的程序来说是理想的;
- 透明调试和简档(profiling)语意--java hotspot体系结构能够使本地代码的生成及优化对程序员完全透明,它可以按照纯字节码语意提供全部简档和调试信息,而不管内部实际上所用的优化方法。
以下部分将介绍java hotspot性能引擎的重要的体系结构及其特性。
4. 内存模型
4.1 无句柄对象
java 2 软件开发工具包(sdk)使用间接句柄来表示对象的引用。虽然在垃圾回收过程中,这样做会使对象的重新定位变得更加简单,但这会引发一个重要的性能瓶颈,因为大多数对java编程语言对象的实例变量的访问都需要两个层次的间接引用。java hotspot性能引擎消除了句柄的概念:对象的引用被实现为直接指针,从而可提供对实例变量的c-速度访问。垃圾回收器则负责在内存被回收过程中,当对象被重新定位时,寻找并更新所有对在适当位置上的对象的引用。
4.2 双字(tow-word)对象头
java hotspot性能引擎使用双机器-字对象头,而不是象java 2 sdk那样使用三字对象头。由于平均的java编程语言的对象尺寸较小,因而这种技术对节省空间产生了重要作用(大约节省了8%的堆的大小)。第一个对象头的字包含了身份标识哈希码和gc状态等信息;第二个对象头的字是一个对对象的类的引用。只有数组才有第三个对象头字段,它是用来表示数组大小的。
4.3 将映射数据表示为对象
类、方法以及其它内部映射数据被直接表示为堆上的对象(尽管这些对象也许不能被基于java技术的程序所直接访问)。这不仅简化了内存模型,而且使你可以采用与回收其它java编程语言对象相同的垃圾回收器来回收这类映射数据。
4.4 本地线程支持,包括任务抢先和多重处理技术
每个线程方法的激活栈是使用宿主操作系统的线程模型来表示的。java编程语言方法和本地方法可共享相同的栈,从而可允许在c和java编程语言间的快速调用。使用宿主操作系统的线程调度机制可支持全抢先的java编程语言线程。
使用本地操作系统的线程和调度机制的一个主要优点是,它能够透明地利用本地操作系统支持多重处理。由于java hotspot性能引擎被设计为对在执行java编程语言代码时的抢先和/或多重处理引起的竞争状态是不敏感的,因而java编程语言线程将自动利用由本地操作系统所提供的任意调度机制和处理器分配策略。
5. 内存垃圾回收
5.1 背景说明
java编程语言对程序员的一个主要魅力在于,它是第一个可提供内置自动内存管理(或内存垃圾回收)的主流编程语言。在传统语言中,一般都使用显式分配/释放模型来进行动态内存分配。事实证明, 这不仅是造成内存泄漏、程序错误以及用传统语言编写的程序崩溃的最主要原因之一,而且还是提高性能的瓶颈, 并且是形成模块化和可再使用代码的主要障碍(如果没有显式和难以理解的模块间的协同操作,在模块界限间确定释放点有时几乎是不可能的)。在java编程语言中,垃圾回收也是支持安全性模型所必需的所谓"安全地"执行这一语义的重要组成部分。
当一个垃圾回收器能够"证明"某个对象对正在运行的程序来说是不可访问的时候,它仅通过回收该对象就可自动地在后台处理对该对象的内存的"释放"。这种自动的处理过程不仅完全消除了由于释放太少而引起的内存泄漏,同时也消除了由于释放太多而引起的程序崩溃和难以发现的引用错误。
从传统上讲,相对于显式释放模型来说, 垃圾回收一直被认为是一种没有效率且会引起性能下降的处理过程。事实上,使用现代垃圾回收技术,可大大改善性能,且这种性能实际上要比由显式释放所提供的性能好得多。
5.2 java hotspot垃圾回收器