「每日五分钟,玩转JVM」:指针压缩

450 阅读2分钟

64位JVM和32位JVM

最初的时候,JVM是32位的,但是随着64位系统的兴起,JVM也迎来了从32位到64位的转换,32位的JVM对比64位的内存容量比较有限,但是我们使用64位虚拟机的同时,也带来了一个问题,64位下的JVM中的对象会比32位中的对象多占用1.5倍的内存空间,这是我们不想看到的(又要马儿跑,又要马儿不吃草可还行?),但是机智的程序员不会屈服,所以在JDK 1.6的版本后,我们在64位中的JVM中可以开启指针压缩(UseCompressedOops)来压缩我们对象指针的大小来帮助我们节约内存空间,拿JDK 8来说,这个指令是默认开启的。

如果我想要知道我们电脑上安装的JVM是32位的还是64位的,可以通过下面的这个命令去查看

如果我们的系统是64位的,当我们输入java -d32的时候会提示不支持32位的JVM,或者我们通过java -version也可以看到:

image-20190911201937600

指针压缩

当我们启用了-XX:+UseCompressedOops之后,我们原本的OOP(Ordinary Object Pointer,普通对象指针)就会被压缩,当然也不是所有的对象都会被压缩,只有 以下几种的对象才会被压缩

对象的全局静态变量(类属性)

对象头信息

对象的引用类型

对象数组类型

而以下几种对象则不能被压缩:

指向PermGen的Class对象指针

局部变量

传参

返回值

NULL指针

指针压缩的大概原理:

  • 通过对齐,还有偏移量将64位指针压缩成32位。

  • 零基压缩是针对压缩解压动作的进一步优化。 它通过改变正常指针的随机地址分配特性强制堆地址从零开始分配

image-20190911203525671

这里需要注意:32位HotSpot VM是不支持UseCompressedOops参数的,只有64位HotSpot VM才支持。

下面是32bit和64bit下的压缩或者不压缩所占的大小~

image-20190911221738200

在内存结构中的不同

image-20190823231212050

公众号