class共享池

随着多核和虚拟化技术的发展,多个JVM实例之间共享信息带来的性能提升很明显,OracleJDK 5.0开始加入了“CDS”特性,IBM SDK5.0中针对z/OSi5/OS也加入了持久复用和bytecode校验缓存功能。IBM的虚拟机J9在这方面做了特殊处理。

 IBM SDK 6.0开始,J9加入了class 共享 (class data sharing)。使得在同一台机器上运行的多个JVM实例可以透明的、动态的共享数据,包括加载的class文件、AOT(详见3.2)、常用的UTF-8 string  jar文件的索引。

对于class文件,JVM在加载时内部会将其分成两个部分,只读部分和可写部分。Class共享功能所共享的是class的只读部分,这么做可以减少多个JVM实例运行时内存的开销,也可以提高JVM实例启动速度,尤其是启动新JVM实例完成一项很小的任务。

当一个class文件会被多个JVM实例加载时,缓存这个class文件方法的AOT码可以提高JIT编译器效率。此外,在class文件共享池中保存的数据会一直保存,甚至会超过创建这些数据的JVM实例的生命周期,这样后续启动的JVM实例在加载相同class文件时,可以从中受益。

使用J9 共享池的注意地方有:

·    J9class共享功能不仅需要SDK 6.0,还需要IBM提供的平台,不支持Oracle Solaris  HP hybrids。对于Windows也不支持。

·    所有加载的class文件保存在class缓存中(class cache),这个缓存分两部分,一部分是保存在硬盘中的映射文件,一个是内存共享,在内存中共享的数据会定时保存至硬盘文件。这个缓存由第一个需要使用的JVM实例分配。

·    JVM链接class共享缓存的权限可以是只读的,也可以是可写的,视具体情况而定。如果设定成只读的,当有许多JVM实例共享相同的缓存时会造成大量的隔离”(isolation)。即每个JVM实例只能修改其本身的数据。

·    在遇到内存分页保护时,class共享缓存也会受到保护。

·    JVM决定在何时往共享缓存中加入多少AOT方法编译码。AOT方法编译码的总量不超过class共享池 空间的10%(由于J9虚拟机自身大部分也是由Java编写的,所以共享池中都肯定保存IBM SDKAOT)

·    class共享池失效或者是共享的数据版本太旧,每个JVM实例可以自行移除或重建已经存在的class共享池。

·    可以从命令行指定共享缓存的本地文件。这个文件可以在当前机器内任意拷贝移动,甚至可以在不同的机器之间复制、移动,前提是它们操作系统和硬件相同。

·    Java类加载器可以设置过滤器,用于限制需要共享的class

·    任何JVM实例都可以读取或更新缓存。

·    如果缓存中数据会一直保存,无论创建它的JVM实例是否结束,除非有明确移除缓存数据的请求。在操作系统宕机时,保存在硬盘的缓存数据(z/OS系统不可用)可以保存,但内存中的数据将丢失。

·    JVM实例加载类时,首先检查其对应的class共享池,如果共享池中有这个类,则从共享池中加载,如果没有则从硬盘加载并放入class共享池。

·    当共享池空间耗尽时,不再加载新的数据。

·    class共享缓存中的数据保存时间可能会超过任意JVM实例,这样有可能造成class共享数据过期,因为同一个class文件可以修改后再次加载。所以所有的共享数据都有自己的版本号用于JVM实例在需要的时候更新数据。

·    class共享池支持共享转换和重定义后的字节码(AOT),不过使用时得谨慎。

·    如果安装了安全管理系统(security manager),那么链接class共享数据会受到Java许可的保护。

 

你可能感兴趣的:(java,jvm,class共享池)