JVM-对象的指针压缩

什么是java对象的指针压缩?
1.jdk1.6 update14开始,在64bit操作系统中,JVM支持指针压缩
2.jvm配置参数:UseCompressedOops,compressed--压缩、oop--对象指针
3.启用指针压缩:-XX:+UseCompressedOops,禁止指针压缩:-XX:-UseCompressedOops

为什么要进行指针压缩?
1.在64位平台的HotSpot中使用32位指针,内存使用会多出1.5倍左右,使用较大指针在主内存和缓存之间移动数据,占用较大宽带,同时GC也会承受较大压力
2.为了减少64位平台下内存的消耗,启用指针压缩功能
3.在jvm中,32位地址表示4G个对象的指针,在4G-32G堆内存范围内,可以通过编码、解码方式进行优化,使得jvm可以支持更大的内存配置
4.堆内存小于4G时,不需要启用指针压缩,jvm会直接去除高32位地址,即使用低虚拟地址空间
5.堆内存大于32G时,压缩指针会失效,会强制使用64位(即8字节)来对java对象寻址,这就会出现1的问题,所以堆内存不要大于32G为好

指针压缩的原理是什么?
1.解释器解释字节码,植入压缩指令,进行编码、解码
2.需要操作系统底层支持:GC堆从虚拟地址0开始分配

哪些信息会被压缩?
1.对象的全局静态变量(即类属性)
2.对象头信息:64位平台下,原生对象头大小为16字节,压缩后为12字节
3.对象的引用类型:64位平台下,引用类型本身大小为8字节,压缩后为4字节
4.对象数组类型:64位平台下,数组类型本身大小为24字节,压缩后16字节

哪些信息不会被压缩?
1.指向非Heap的对象指针
2.局部变量、传参、返回值、NULL指针

实际演练:

基于上一节:JAVA-如何计算一个对象的大小

测试代码做简单修改:

/**
 * @author ignore1992
 *
 * 2018-6-26
 */
public class Main
{
public static void main(String[] args)
{
//1.测试包含非基本类型属性的对象大小
System.out.println(String.format("sizeof(new A):%s", ObjectSizeService.sizeOf(new A())));
//2.测试包含非基本类型属性的对象大小
System.out.println(String.format("sizeof(new B):%s", ObjectSizeService.sizeOf(new B())));
//3.测试基本类型数组对象的大小
System.out.println(String.format("sizeof(new int[0]):%s", ObjectSizeService.sizeOf(new int[0])));
System.out.println(String.format("sizeof(new int[1]):%s", ObjectSizeService.sizeOf(new int[1])));
//4.测试非基本类型数组对象的大小
System.out.println(String.format("sizeof(new A[0]):%s", ObjectSizeService.sizeOf(new A[0])));
System.out.println(String.format("sizeof(new A[1]):%s", ObjectSizeService.sizeOf(new A[1])));
}
}
class A
{
	//基本类型
	int a = 0;
}
class B
{
	//引用类型
	Integer b = 0;
}

不启用指针压缩,执行:
java -javaagent:java-objectsize-0.0.1-SNAPSHOT.jar -XX:-UseCompressedOops -jar java-objectsize-0.0.1-SNAPSHOT.jar
日志打印如下:
sizeof(new A):24
sizeof(new B):24
sizeof(new int[0]):24
sizeof(new int[1]):32

启用指针压缩,执行:
java -javaagent:java-objectsize-0.0.1-SNAPSHOT.jar -XX:+UseCompressedOops -jar java-objectsize-0.0.1-SNAPSHOT.jar
日志打印如下:
sizeof(new A):16
sizeof(new B):16
sizeof(new int[0]):16
sizeof(new int[1]):24

可以根据上面打印的日志以及前面提到的指针压缩做简要的分析:
1.未开启指针压缩:
sizeof(new A):24 ---对象头(16字节)+实例数据(基本类型4字节)+对齐填充(4字节)
sizeof(new B):24 ---对象头(16字节)+实例数据(引用类型8字节)+对齐填充(0字节)
sizeof(new int[0]):24 ---对象头(24字节)+实例数据(0字节)+对齐填充(0字节)
sizeof(new int[1]):32 ---对象头(24字节)+实例数据(基本类型4字节)+对齐填充(4字节)

2.开启指针压缩:
sizeof(new A):16 ---对象头(压缩后12字节)+实例数据(基本类型4字节)+对齐填充(0字节)
sizeof(new B):16 ---对象头(压缩后12字节)+实例数据(压缩后引用类型4字节)+对齐填充(0字节)
sizeof(new int[0]):16 ---对象头(压缩后16字节)+实例数据(0字节)+对齐填充(0字节)
sizeof(new int[1]):24 ---对象头(压缩后16字节)+实例数据(基本类型4字节)+对齐填充(4字节)

转载自:JVM-对象的指针压缩

你可能感兴趣的:(Java)