随着多核和虚拟化技术的发展,多个JVM实例之间共享信息带来的性能提升很明显,Oracle从JDK 5.0开始加入了“CDS”特性,IBM SDK5.0中针对z/OS、i5/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 共享池的注意地方有:
· J9的class共享功能不仅需要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 SDK的AOT码)
· 当class共享池失效或者是共享的数据版本太旧,每个JVM实例可以自行移除或重建已经存在的class共享池。
· 可以从命令行指定共享缓存的本地文件。这个文件可以在当前机器内任意拷贝移动,甚至可以在不同的机器之间复制、移动,前提是它们操作系统和硬件相同。
· Java类加载器可以设置过滤器,用于限制需要共享的class。
· 任何JVM实例都可以读取或更新缓存。
· 如果缓存中数据会一直保存,无论创建它的JVM实例是否结束,除非有明确移除缓存数据的请求。在操作系统宕机时,保存在硬盘的缓存数据(z/OS系统不可用)可以保存,但内存中的数据将丢失。
· 当JVM实例加载类时,首先检查其对应的class共享池,如果共享池中有这个类,则从共享池中加载,如果没有则从硬盘加载并放入class共享池。
· 当共享池空间耗尽时,不再加载新的数据。
· class共享缓存中的数据保存时间可能会超过任意JVM实例,这样有可能造成class共享数据过期,因为同一个class文件可以修改后再次加载。所以所有的共享数据都有自己的版本号用于JVM实例在需要的时候更新数据。
· class共享池支持共享转换和重定义后的字节码(即AOT码),不过使用时得谨慎。
· 如果安装了安全管理系统(security manager),那么链接class共享数据会受到Java许可的保护。
相关推荐
### Java Class 文件中的常量池类型分类 在Java中,每个`.class`文件都包含一个常量池(Constant Pool),它是一个特殊的数据结构,用于存储类或接口的编译期常量,包括直接引用到其他类、字段和方法的信息。常量池...
- **Class共享池**: 存储预编译过的代码,加速程序启动和执行速度。 - **JIT编译器**: 将热点代码编译成本地机器码,提高执行效率。 - **JIT编译器优化编译工作原理**: 动态识别热点代码并进行优化。 - **AOT编译器...
应用时,先用rar打开jar包,拷贝r2.properties文件到class目录,并修改参数。 本包需要用到log4j,请在调用时确保存在log4j的jar包。 单池调用方式为Connection conn = R2PoolUtil.getStaticPool().getConnection();...
数据库的连接池是一种在应用程序中管理数据库连接的高效机制,它允许多个并发的数据库操作共享一组预先建立的数据库连接,而不是每次需要时都创建新的连接。这样可以显著提高应用程序的性能,减少系统资源的消耗,并...
`sessionName`是Session ID的名称,`maxActive`, `maxIdle`, 和 `minIdle` 控制连接池大小,`processExpiresFrequency` 是检查并清理过期Session的频率。 3. **配置Redis Session Store**:下载并添加Redis Session...
K8S通过StorageClass为用户提供了一种管理持久卷(Persistent Volumes, PV)的方式,使得存储资源的分配可以自动化进行。本文将深入探讨K8S监控中的NFS(Network File System)动态storageClass存储,帮助管理员更好...
为了构建一个灵活且通用的对象池,可以在创建对象池时动态指定所要池化的对象的Class类型。这意味着开发者可以根据具体需求选择不同的对象类型放入池中,提高了对象池的适应性和可扩展性。 #### 使用对象池技术时的...
4. **配置Web应用**:在每个Web应用的`web.xml`中,定义`session-config`,设置`manager-class`为`org.apache.catalina.session.ManagerBase`,并添加Redis相关的初始化参数。 5. **测试与优化**:启动Tomcat,验证...
在C#中,数据库连接池是一种高效的资源管理技术,它允许多个数据库操作共享一个数据库连接,而不是每次操作都创建新的连接。这样做可以显著减少打开和关闭连接的开销,提高应用程序性能,并减少数据库服务器的压力。...
- `omp_get_max_threads()`: 获取线程池的最大线程数量。 #### 5. 示例 下面是一个使用JOMP进行简单并行计算的例子,计算一个数组元素的总和: ```java public class ParallelSum { public static void main...
4. **全局共享实例**:为了确保在整个应用中只有一个连接池实例,通常使用单例模式来创建和管理连接池类。 以下是一个简单的连接池实现的步骤: **步骤一**:创建`ConnManagerPool`类,定义连接参数和连接栈,以及...
数据库连接池是一种容器,它预先创建一定数量的数据库连接,并将这些连接保存在一个可共享的池子中。当应用程序请求数据库连接时,连接池会提供一个现有的连接,而无需重新建立一个新的连接。这种方式大大减少了...
连接池是一种在应用程序启动时预创建一定数量的数据库连接,供多个线程共享使用的机制。当应用需要访问数据库时,可以从连接池中获取一个已存在的连接,用完后归还而不是关闭,从而避免了频繁地创建和销毁连接带来的...
3. **配置RedisSessionManager**: 在每个Tomcat实例的`server.xml`中,添加`GlobalNamingResources`下的`Resource`元素,以定义全局的Redis连接池。 ```xml <!-- ... --> auth="Container" type="redis....
在Tomcat的`web.xml`配置文件中,需要修改`<session-config>`标签,设置`Manager`类为`org.apache.catalina.session.PersistentManager`,并配置相关属性如`storeClass`为`org.apache.catalina.session.RedisStore`...
public class RedisConfig { @Value("${redis.host}") private String redisHost; @Value("${redis.port}") private int redisPort; @Bean public JedisConnectionFactory jedisConnectionFactory() { ...