JVM优化之压缩普通对象指针(CompressedOops)

一般64位JVM消耗的内存会比32位的大1.5倍,这是由于对象指针在64位架构下,长度会翻倍(更宽的寻址)。
对于那些将要从32位平台移植到64位的应用来讲,平白无辜多了1/2的内存占用,这是开发者不肯意看到的。
幸运的是,从JDK 1.6 update14开始,64 bit JVM正式支持了 -XX:+UseCompressedOops 这个能够压缩指针,起到节约内存占用的新参数。java

 

什么是 OOP ?

OOP = “ordinary object pointer” 普通对象指针。数组

启用CompressOops后,会压缩的对象:
• 每一个Class的属性指针(静态成员变量)
• 每一个对象的属性指针
• 普通对象数组的每一个元素指针架构

固然,压缩也不是万能的,针对一些特殊类型的指针,JVM是不会优化的。
好比指向PermGen的Class对象指针,本地变量,堆栈元素,入参,返回值,NULL指针不会被压缩。ide

 

怎么启用?

在启动java时,加 -XX:+UseCompressedOops (须要jdk1.6.0_14)oop

 

CompressedOops的原理

原理,解释器在解释字节码时,植入压缩指令(不影响正常和JVM优化后的指令顺序)。
具体逻辑是,当对象被读取时,解压,存入heap时,压缩。优化

压缩指令伪码spa

! int R8; oop[] R9; // R9 is 64 bits
! oop R10 = R9[R8]; // R10 is 32 bits
! load compressed ptr from wide base ptr:
movl R10, [R9 + R8<<3 + 16]
! klassOop R11 = R10._klass; // R11 is 32 bits
! void* const R12 = GetHeapBase();
! load compressed klass ptr from compressed base ptr:
movl R11, [R12 + R10<<3 + 8]指针

 

零基压缩优化(Zero Based Compressd Oops)

零基压缩是针对压解压动做的进一步优化。
它经过改变正常指针的随机地址分配特性,强制从零开始作分配(须要OS支持),进一步提升了压解压效率。对象

要启用零基压缩,你分配给JVM的内存大小必须控制在4G以上,32G如下。
若是小于4G,那么JVM会使用低虚拟地址空间(low virutal address space,64位下模拟32位),这样就不须要作压解压动做了。
而对于大于32G,将采用默认的随机地址分配特性,进行压解压。内存

 

适用场景

CompressedOops,能够让跑在64位平台下的JVM,不须要由于更宽的寻址,而付出Heap容量损失的代价。不过,它的实现方式是在机器码中植入压缩与解压指令,可能会给JVM增长额外的开销。

相关文章
相关标签/搜索