指针压缩原理和为什么指针压缩只能压缩3位

1 聊指针压缩前明白几个大前提
  1,java对象是8字节对其的,或者说3个字节对齐的。
  2,一个字节是8个二进制位。
  3,4字节能表示多大数据? 2的32次方=4G 个二进制位的数据,也就是512M

  4,带宽用的单位是1K 表示2的10次方位,硬盘内存用的1K是2的10次方字节,也就是硬盘内存寻址是按照最低1字节对齐的方式来查找的。

 

2为什么要指针压缩
  java开启指针压缩指针用4字节表示,不开启用8字节表示,指针如果使用64位的,会增加大量的内存开销,和内存带宽占用。

 


3 4字节,32位的指针只能表示4G个二进制位的数据按照1字节对齐以后,最多可以管理4G的内存,ssd要求最低4K对齐才能发挥其性能。

  java开启指针压缩后最大理论支持 32G内存,是4G的8倍,怎么做的的?因为Java对象是8字节对齐的( 8是2的3次方  )

  如果按照8个二进制对齐(1字节8位),32 位的指针可以管理4G(512*8)内存。如果8个这样分分区在一次对齐(Java8 字节对齐),32位的指针就可以管理32G(4G*8)内存

   

  

 

 

    所以有人说Java如果32G内存不够,在指针后面多补一个0 就能扩容内存,是不对的,最多只能是3位。如果要能多补一个0来增加最大内存容量,前提是Java使用16字节对齐(头8+4,这样一算感觉好像比8字节对齐更加好,毕竟最小的Java对象需要16字节)。

   继续的 扩容需要 32 位对齐,比8+4打了不少,完全是Java会多消耗2倍以上的内存,容量增加了,能装的对象却不会增加。


4 Java 用32位的地址管理者43位二进制能表示的内存空间,或者说35位1字节对齐的空间

   可以理解成 32位指针指向 了一个3*8的二维数组,我们用这个数组管理者2的11次方种可能的值,我们不管里面是什么每次要找这个格子11低位前面的32高地址就可以了(相对1字节对齐是3低位的其它32高位)。

 


 

  总结就一句话:因为有对象对其带来的逻辑分区,实际指针指向分区就可以了,这就是指针压缩算法的原理。理论指针压缩最多可以用 32位 +3位个字节的空间,也就是32G。



5 指针压缩以后,java对象区域内如果有 一个字节的Byte类型,甚至一位的 Boolean 类型怎么表示,怎么访问

  

 

  如果我们有个 对象是 一个字节的对象new Byte("1"),他们在 堆内存中占的是 1字节。他们的对象实例区数据很少,比一个指针还小,但是依旧要占用 16 字节(头8+4,实例区1,对其区3)。
  如果 我们是 直接 byte a = 1,boolean b = true ,这时候对象不会放在堆内存,而是当做常量

  java 如果使用 new Byte("1"),new Boolean(true),这种并不会省内存空间,因为对其以后都一样。直接用 new Integer 一样的空间占用。(头8+4,实例区4,对齐区0)

  比如User 里面有 一个 boolean a ,实例区里面不是放的一位的数据,而是一个4字节的对象指针。这个对象指针指向 一个16字节的对象,这个对象有8+4字节的头,这个对象实例数据里面第一个字节的第一位用来表示这个对象的值,后面还有3字节的填充区。

  我们访问 user.a 的时候,先找到user 对象里面a的指针,然后再找到a的实例,不会直接得到user.a的指针,32位的指针只会把它低位补3个0来范围字节,补11个0来访问二进制位,然后通过对象结构便宜吧后面的0 换成对应的内存真实地址。

 

 


  所以Java的使用指针压缩只能使用最大理论32G内存,如果超过32 G内存就只能使用64位指针。如果低于4G指针压缩算法都没必要开启,直接用正常的32位指针就够了。

  实际64 位的指针太长了,用来寻址实在用不完,指针上面就可以存写别的,比如ZGC染色指针用了2位作为三色标记,1位作为读屏是否需要触发障标记,1位作为ffanaze后对象的状态记录。基本这样用了,还有不少高位空间是空闲。

posted on 2022-04-25 16:14  zhangyukun  阅读(816)  评论(0编辑  收藏  举报

导航