指针膨胀

指针膨胀:64位jvm寻址范围较32位变成了64位,叫做指针膨胀;
在32位虚拟机中,本地指针占用4字节,在64位虚拟机中本地指针占用8字节数据类型对齐补白:Java原始数据类型的长度是固定的,但是对于不同的平台本地数据类型长度并不固定,当JVM中调用本地(Native)方法时,它们之间交互的数据,比如一个int,在java中一定为32位的,但是在本地实现中(比如C/C++)可能是64位的,多出来的那部分就需要补0来对齐。(应该是这样的,这个不是很重要,不必很纠结了)

数据类型对齐补白

64位数据补白:数据在64位jvm中存储较之32位jvm需要对数据位进行对齐补白;
JVM在创建对象的时候,会有一个内存对齐的概念;如

  • 1、 一个空对象占用8字节( 空对象:占8字节 64位bit )
  • 2、 只有一个 boolean 字段的类实例占 16 字节:头信息占 8 字节,boolean 占 1 字节,为了对齐达到 8 的倍数会额外占用 7 个字节
  • 3、 包含 8 个 boolean 字段的实例也会占用 16 字节:头信息占用 8 字节,boolean 占用 8 字节;因为已经是 8 的倍数,不需要补充额外的数据来对齐
  • 4、 一个包 2个 long 字段、3个 int字段、1 个 boolean 字段的对象将占用:头信息占 8 字节;2 个 long 字段占 16 字节(每个 long 字段占用 8 字节);3 个 int 字段占 12 字节(每个 int 字段占用 4 字节);1 个 boolean 字段占 1 个字节; 上面加起来是 37 字节, 为了对齐额外多的 3 个字节,需求对齐 ,为8 的倍数 40

int 4字节byte 32 bit
boolean 占8分之1字节 1位bit
char 1个字节 8 bit
short 2字节 16 bit
float 4字节byte 32位bit;
long 8字节byte 64位bit;
double 占8字节byte 64位bit;
注意: 32位64位操作系统基本数据类型字节大小,只要注意long: 32位: long: 4个字节 64位: long: 8个字节
boolean会占用一比特或者占用一个字节的第八位,但是HotSpot虚拟机会为每个Boolean字段分配一个字节的空间
在 Java 虚拟机中没有任何供 boolean 值专用的字节码指令,在 Java 语言之中涉及到 boolean 类型值的运算,在编译之后都使用 Java 虚拟机中的 int 数据类型来代替。 Java 虚拟机直接支持 boolean 类型的数组,虚拟机的 newarray 指令可以创建这种数组。boolean 的数组类型的访问与修改共用 byte 类型数组的 baload 和 bastore 指令。综上所述, 单个boolean型是占4字节(因为变异后会用int来代替), 而boolean数组中的则占1字节(因为用byte来代替的)

因为以上原因64位jvm通常需要更多的内存,比32位jvm多10%到30%,在主流测试环境中64位jvm测试速度也比32位jvm落后,性能差15%左右。
所以很多工程师在采用32位集群方式部署应用,但这种方案也有缺陷:
1、集群节点可能竞争全局资源;
2、一些资源池比如连接池可能利用率不高,因为一般情况下各个节点都有自己的连接池,可能出现有的节点连接池满了,有的节点连接池有较大空余;可以用JNDI改善此类情况但又有性能开销和复杂度。
3、各个节点最高4G的限制,windows下只有2G,堆内存最大可能为1.5G左右。
在jdk1.6 update14之后,sun提供了指针压缩功能(-XX:+ UseCompressedOops),执行代码时动态加入压缩指令以减少内存消耗,但同时会增加代码数量,所有heap内的指向heap内对象的指针都会压缩。
32位JVM的最大理论堆限制为4G。由于各种附加约束,例如可用交换,内核地址空间使用,内存碎片和VM开销,实际上限制可以低得多。在大多数现代32位Windows系统上,最大堆大小范围为1.4G到1.6G。在32位Solaris内核上,地址空间限制为2G。在运行32位VM的64位操作系统上,最大堆大小可能更高,在许多Solaris系统上接近4G。
从Java SE 6开始,不支持Windows / 3GB boot.ini功能。
许多Java用户和开发人员都认为64位实现意味着许多内置Java类型的大小从32增加到64倍。但事实并非如此。我们没有将Java整数的大小从32增加到64,因为Java长度已经是64位宽,所以它们不需要更新。在Java虚拟机规范中定义的数组索引不会从32扩展到64.我们在创建第一个64位Java端口时非常小心,以确保Java二进制和API兼容性,因此所有现有的100%纯Java程序将像在32位VM下一样继续运行。