1.JOL
1 2 3 4 5
| <dependency> <groupId>org.openjdk.jol</groupId> <artifactId>jol-core</artifactId> <version>0.9</version> </dependency>
|
1 2 3 4 5 6
| print(ClassLayout.parseInstance(obj).toPrintable()); print(GraphLayout.parseInstance(obj).toPrintable()); print("size : " + GraphLayout.parseInstance(obj).totalSize());
|
2. lucene提供的专门用于计算堆内存占用大小的工具类:RamUsageEstimator,maven坐标:
1 2 3 4 5
| <dependency> <groupId>org.apache.lucene</groupId> <artifactId>lucene-core</artifactId> <version>4.0.0</version> </dependency>
|
常用的方法
1 2 3 4 5 6 7 8 9
| long RamUsageEstimator.sizeOf(Object obj)
long RamUsageEstimator.shallowSizeOf(Object obj)
String RamUsageEstimator.humanSizeOf(Object obj)
|
1 2 3 4 5
| public static void main(String[] args) { final byte[] sLock = new byte[0]; System.out.println(RamUsageEstimator.sizeOf(new Object())); System.out.println(RamUsageEstimator.sizeOf(sLock)); }
|
默认开启指针压缩 -XX:+UseCompressedOops
关闭指针压缩 -XX:- UseCompressedOops
简单好用,锁的话就用new Object()
3.关闭指针压缩为什么大了8个字节?
大了4个字节,加上要内存对齐8个字节。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| object---------------------------------------------- 查看对象内部信息 java.lang.Object object internals: OFFSET SIZE TYPE DESCRIPTION VALUE 0 4 (object header) 01 00 00 00 (00000001 00000000 00000000 00000000) (1) 4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0) 8 4 (object header) 00 1c c3 1c (00000000 00011100 11000011 00011100) (482548736) 12 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0) Instance size: 16 bytes Space losses: 0 bytes internal + 0 bytes external = 0 bytes total
查看对象外部信息 java.lang.Object@aec6354d object externals: ADDRESS SIZE TYPE PATH VALUE 1288d8b18 16 java.lang.Object (object)
获取对象总大小 size : 16 sLock---------------------------------------------- 查看对象内部信息 [B object internals: OFFSET SIZE TYPE DESCRIPTION VALUE 0 4 (object header) 01 00 00 00 (00000001 00000000 00000000 00000000) (1) 4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0) 8 4 (object header) a8 07 c3 1c (10101000 00000111 11000011 00011100) (482543528) 12 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0) 16 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0) 20 4 (alignment/padding gap) 24 0 byte [B.<elements> N/A Instance size: 24 bytes Space losses: 4 bytes internal + 0 bytes external = 4 bytes total
查看对象外部信息 [B@41975e01d object externals: ADDRESS SIZE TYPE PATH VALUE 1288d8b00 24 [B []
获取对象总大小 size : 24
|
开启指针压缩
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| object---------------------------------------------- 查看对象内部信息 java.lang.Object object internals: OFFSET SIZE TYPE DESCRIPTION VALUE 0 4 (object header) 01 00 00 00 (00000001 00000000 00000000 00000000) (1) 4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0) 8 4 (object header) e5 01 00 f8 (11100101 00000001 00000000 11111000) (-134217243) 12 4 (loss due to the next object alignment) Instance size: 16 bytes Space losses: 0 bytes internal + 4 bytes external = 4 bytes total
查看对象外部信息 java.lang.Object@aec6354d object externals: ADDRESS SIZE TYPE PATH VALUE 76be9bd30 16 java.lang.Object (object)
获取对象总大小 size : 16 sLock---------------------------------------------- 查看对象内部信息 [B object internals: OFFSET SIZE TYPE DESCRIPTION VALUE 0 4 (object header) 01 00 00 00 (00000001 00000000 00000000 00000000) (1) 4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0) 8 4 (object header) f5 00 00 f8 (11110101 00000000 00000000 11111000) (-134217483) 12 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0) 16 0 byte [B.<elements> N/A Instance size: 16 bytes Space losses: 0 bytes internal + 0 bytes external = 0 bytes total
查看对象外部信息 [B@41975e01d object externals: ADDRESS SIZE TYPE PATH VALUE 76be9bd20 16 [B []
获取对象总大小 size : 16
Process finished with exit code 0
|
不管是否开启指针压缩,数组引用类型要多一个 4个字节的长度 的标记。
1
| Object object = new Object[0x0FFFFFFF];
|
验证
1 2 3 4 5 6 7 8 9 10 11 12 13
| object---------------------------------------------- 查看对象内部信息 [Ljava.lang.Object; object internals: OFFSET SIZE TYPE DESCRIPTION VALUE 0 4 (object header) 01 00 00 00 (00000001 00000000 00000000 00000000) (1) 4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0) 8 4 (object header) 38 cb 6c 1c (00111000 11001011 01101100 00011100) (476891960) 12 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0) 16 4 (object header) ff ff ff 0f (11111111 11111111 11111111 00001111) (268435455) 20 4 (alignment/padding gap) 24 2147483640 java.lang.Object Object;.<elements> N/A Instance size: 2147483664 bytes Space losses: 4 bytes internal + 0 bytes external = 4 bytes total
|
那我要是直接声明一个 长整型 [long]的呢?
对不起,不支持!
为什么???
Java 中数组的最大长度是多少呢?看一下它的length属性就可以了。length属性是32位的有符号整数,它的最大值是2的31次幂,就是2G。为何有这个限制呢?为什么length的属性不是long型呢?我们假设一下,如果它是long型的,那么它的最大长度是2的63次幂。内存永远也不会有那么大吧。即使是字节数组长度是int的,最大长都达到2GB.
由此想到了String,这个家伙底层也是基于数组的,是一个字符数组。字符是16位的基本类型,一个String的最大长度是多少呢?就是字符数组的最大长度也是2G,占用内存是4GB。
从JVM的角度来解释:创建数组的字节码是anewarray和newarray,操作数栈的字宽是32位,而这两个字节码的参数都是一个字长,所以无法接受long型的长度参数。不知道这样解释是否很牵强。