Developer Connection

Member Login 登录 | 不是会员?

ADC 首页 > 技术文档 > Java > Mac OS X平台上的Java 1.4.1开发



Previous Next

Mac OS X的Java共享档案

为了提高Java应用程序的启动速度,减少内存印迹,Mac OS X的Java虚拟机使用了Java共享档案技术(JSA)。JSA包含公用的标准Java类的内部HotSpot表示文件,系统对这些表示文件进行了预处理。如果没有用JSA技术,则系统需要从标准的classes.jar文件中寻找和处理这些Java类,然而考虑到这些标准Java类的数据不会发生改变,可以把这些JSA文件直接映射到共享内存中,在进程之间共享。JSA文件是在系统安装Java后的首次启动过程中创建的。由于不需要为每一个Java应用程序生成独立的JSA文件,所以这种技术可以减少对内存和CPU资源的占用,而您不需要任何编程就可以得到这些优势。本文将对这种技术作简要的介绍。

这个部分包括以下内容:

世代式垃圾收集机制(Generational Garbage Collection )
Java共享档案的优势

世代式垃圾收集机制(Generational Garbage Collection )

垃圾收集(GC)是一种使Java虚拟机释放不再使用的对象所占用的资源的手段。Java程序员提供了一个环境,在这个环境中对象及其所占用的内存可以回收,而不需要程序员的参与。 GC是一种运行时的工具,已经有数十年的开发历史了,其基本想法如下:在内存中有一个根对象的集合,这些根对象引用了另外的一些对象,而这些被引用的对象又反过来引用了其他对象,依次类推。如果一个对象不能从根对象沿着一定路径到达,就被声明为垃圾对象,它所占用的内存空间也会被回收。检索所有的对象的开销非常大,所以大约在二十年前,人们就引入了世代式垃圾收集机制。

世代式GC利用了以下事实:绝大部分对象在“年轻时”就“死亡”了。这就是说,绝大多数的对象,比如一个字符串缓冲区,只被使用很短的时间。在世代式GC中,系统会在新对象创建的地方保留一部分内存。这部分内存被填满后,对象会被拷贝到另一片内存中。我们把这些内存片称为“世代”(generation)。HotSpot虚拟机对这些对象进行跟踪,以便在收集垃圾时可以找到从该对象返回根对象的连接。

在GC刚刚运行起来时,正在被使用的对象可能会向上移动到使用代(tenured generation)。绝大多数的世代有自己的策略,以便在不搜索整个内存空间的前提下把那些不再使用的对象挑选出来,而最老的一代并则没有这样的策略。缺省的垃圾收集场景如图7-1所示。

图7-1 缺省的世代式垃圾收集机制

[image: ../art/basic_gc_diagram.gif]

这种机制有一个问题,即当垃圾收集器作用于长久代(permanent generation)时,需要花费一定的时间来进行整个内存空间的检索。而且在很多时候,如果应用程序有多个实例,则这些实例在运行结束时各自长久代内存中会存在很多相同对象。如果用户运行多个Java的应用程序,则这些应用程序的长久代中经常会有相同的资源,因而导致内存的浪费。图7-2说明了这种资源重复问题。

图 7-2 在长久代中的资源重复问题

[image: ../art/duplication.gif]

Sun公司出版了两本技术白皮书,提供了更多Java HotSpot虚拟机的垃圾收集机制的信息,一本是The Java HotSpot Virtual Machine, v1.4.1,可以在从 http://java.sun.com/products/hotspot/docs/whitepaper/Java_Hotspot_v1.4.1/Java_HSpot_WP_v1.4.1_1002_1.html下载; 另一本是Tuning Garbage Collection with the 1.3.1 Java TM Virtual Machine,位于http://java.sun.com/docs/hotspot/gc/index.html页面上。


Java共享档案的优势

为了解决在长久代中的内存浪费问题,苹果公司使用了Java共享档案(Shared Archive)技术。这个技术类似于基于C语言的共享库,它使每个Java应用程序不必在长久代中保留一个独立的资源拷贝,而是与其他应用程序共享同一个拷贝,这些拷贝存在于一个新增的被称为永久代(immortal generation)的内存中。永久代和其他世代有一些区别:

Mac OS X启动时,Java虚拟机便以一种特殊的模式启动,创建(或者更新)一个资源档案,该档案很可能最终存在于长久代中。

在这个档案被正确作成后,虚拟机就终止运行,直到用户运行Java程序时才再次启动。当用户启动Java程序时,虚拟机就装载磁盘上首次启动时创建的资源,把它们映射到与Java堆相同的内存空间中。通过使用这个档案,可以加快应用程序启动的时间。

单独一个Java程序在Mac OS X上启动时间比较短,是Mac OS X Java的一个优势。在多个应用程序运行的环境中,共享档案也会使用更少的内存。后续的应用程序不需要为Java共享档案中的资源分配空间,因为系统已经在磁盘中分配了,它们只需要对这些资源进行映射就可以了。如图7-3所示,其结果类似于共享库。由于很多本来应该在长久代中的对象现在存在于永久代,长久代会变得更小一些。

图 7-3 Java共享档案中永久代的实现

[image: ../art/jsa.gif]

苹果公司在Mac OS X上的Java共享档案技术的实现,和Sun公司的Java HotSpot规范完全兼容,并且已经提交给公司,以便在将来的Java中使用。

请注意:只有使用缺省的Java启动类来启动Java时,才会用到Java共享档案技术。使用java.endorsed.dirs或者修改了缺省的起动类路径,都会禁止应用程序使用Java共享档案技术。

总之,虚拟机使用按世代进行区分的堆来为Java类实现过程中所需的内部数据结构分配内存,这些类并不随着时间的改变而改变,也不需要进行垃圾收集。Mac OS X Java虚拟机扩展了HotSpot对于世代的注解,为这些永久对象增加了一个新的世代。这个扩展可以节省内存,同时也可以缩短时间,因为不需要在永久代中搜索“死亡”的对象了。



Previous Next
(Last Updated July 2003)

Gray line