Java对象大小内幕浅析
来源:互联网 发布:国外羽绒服品牌 知乎 编辑:程序博客网 时间:2024/06/06 00:38
最近突发奇想,忽然对Java对象的内存大小感兴趣,去网上搜集了一些资料,并且做一下整理,希望能够各位帮助。
如果:你能算出new String(“abc”)这个对象在JVM中占用内存大小(64位JDK7中压缩大小48B,未压缩大小64B), 那么看到这里就可以结束了~
Java对象的内存布局:对象头(Header),实例数据(Instance Data)和对齐填充(Padding)。
虚拟机的对象头包括两部分信息,第一部分用于存储对象自身的运行时数据,如hashCode、GC分代年龄、锁状态标志、线程持有的锁、偏向线程ID、偏向时间戳等。这部分数据的长度在32位和64的虚拟机(未开启指针压缩)中分别为4B和8B,官方称之为”Mark Word”。
对象的另一部分是类型指针(klass),即对象指向它的类元数据的指针,虚拟机通过这个指针来确定这个对象是那个类的实例。另外如果对象是一个Java数组,那再对象头中还必须有一块用于记录数组长度的数据,因为虚拟机可以通过普通Java对象的元数据信息确定Java对象的大小,但是从数组的元数据中却无法确定数组的大小。
对象头在32位系统上占用8B,64位系统上占16B。 无论是32位系统还是64位系统,对象都采用8字节对齐。Java在64位模式下开启指针压缩,比32位模式下,头部会大4B(mark区域变位8B,kclass区域被压缩),如果没有开启指针压缩,头部会大8B(mark和kclass都是8B),换句话说,
HotSpot的对齐方式为8字节对齐:(对象头+实例数据+padding)%8 等于0 且 0<=padding<8。以下说明都是以HotSpot为基准。
在参考资料2中提到,再JDK5之后提供的java.lang.instrument.Instrumentation提供了丰富的对结构的等各方面的跟踪和对象大小的测量API。但是这个东西需要采用java的agent代理才能使用,至于agent代理和Instrumentation这里就不阐述了,我这里只阐述其使用方式。
在参考资料3中提供了这个类,个人觉得很实用,代码如下所附1所示(代码比较长,索性就放到文章最后了):
这段代码可以直接拷贝,然后将其打成jar包(命名为agent.jar,如果没有打包成功,可以直接下载博主打包好的),注意在META-INF/MANIFEST.MF中添加一行:
- 1
- 1
举个案例,代码如下(博主的系统是64位的,采用的是64位的JDK7):
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
接下来进行编译运行,步骤如下:
- 编译(agent.jar放在当前目录下):javac -classpath agent.jar ObjectSize.java
- 运行:java -javaagent:agent.jar ObjectSize(输出结果:16,至于这个结果的分析,稍后再阐述)
JDK6推出参数-XX:+UseCompressedOops,在32G内存一下默认会自动打开这个参数。可以在运行参数中添加-XX:-UseCompressedOops来关闭指针压缩。
使用Instrumentation来测试对象的大小,只是为了更加形象的表示一个对象的大小,实际上当一个对象建立起来的时候可以手动计算其大小,代码案例实践用来证明理论知识的合理性及正确性,具体算法在下面的代码案例中有所体现。
补充:原生类型(primitive type)的内存占用如下:
引用类型在32位系统上每个占用4B, 在64位系统上每个占用8B。
案例分析
扯了这么多犊子,估计看的玄乎玄乎的,来几段代码案例来实践一下。
案例1:上面的new Object()的大小为16B,这里再重申一下,博主测试机是64位的JDK7,如无特殊说明,默认开启指针压缩。
- 1
- 1
案例2:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
输出结果:
- 1
- 2
- 1
- 2
分析1(指针压缩):
- 1
- 2
- 3
- 1
- 2
- 3
分析2(指针未压缩):
- 1
- 2
- 3
- 1
- 2
- 3
案例3
- 1
- 2
- 3
- 4
- 1
- 2
- 3
- 4
输出结果:
- 1
- 2
- 1
- 2
分析1(指针压缩):
- 1
- 2
- 3
- 4
- 5
- 1
- 2
- 3
- 4
- 5
分析2(指针未压缩):
- 1
- 2
- 3
- 4
- 5
- 1
- 2
- 3
- 4
- 5
案例4(sizeOf只计算本体对象大小,fullSizeOf计算本体对象大小和引用的大小,具体可以翻阅附录1的代码).
- 1
- 2
- 3
- 1
- 2
- 3
输出结果:
- 1
- 2
- 1
- 2
分析1(指针压缩):
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
分析2(指针未压缩)
- 1
- 2
- 3
- 4
- 1
- 2
- 3
- 4
这些计算结果只会少不会多,因为在代码运行过程中,一些对象的头部会伸展,mark区域会引用一些外部的空间(轻量级锁,偏向锁,这里不展开),所以官方给出的说明也是,最少会占用多少字节,绝对不会说只占用多少字节。
如果是32位的JDK,可以算一下或者运行一下上面各个案例的结果。
看来上面的这些我们来手动计算下new String()的大小:
1. 指针压缩的情况
- 1
- 1
- 指针未压缩的情况
- 1
- 1
所以一个空的String对象最少也要占用40B的大小,所以大家在以后应该编码过程中要稍微注意下。其实也并不要太在意,相信能从文章开头看到这里的同学敲的代码也数以万计了,不在意这些也并没有什么不妥之处,只不过如果如果你了解了的话对于提升自己的逼格以及代码优化水平有很大的帮助,比如:能用基本类型的最好别用其包装类。
附:agent.jar包源码
- 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
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 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
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
参考资料:
1.《一个Java对象到底占多大内存?》
2.《如何精确地测量java对象的大小》
3.《一个对象占用多少字节?》
4.《深入理解Java虚拟机》周志明著。
- Java对象大小内幕浅析
- Java对象大小内幕浅析
- Java对象大小内幕浅析
- Java面向对象浅析
- JAVA ThreadLocal对象浅析
- JAVA ThreadLocal对象浅析
- java对象克隆浅析
- java 对象的浅析
- Java对象的大小
- Java对象的大小
- Java对象的大小
- java 对象大小
- JAVA 对象大小
- java对象大小
- JAVA 对象大小
- java对象大小
- 分析java的对象创建内幕?
- 浅析JAVA面向对象思想
- 冒泡排序 js
- ScrollView滑动悬停ToolBar效果实现
- android intent打开各种文件的方法
- [Android新手学习笔记23]-如何使用ListView展示列表数据
- P08: 泛化物品
- Java对象大小内幕浅析
- [TPYBoard-Micropython之会python就能做硬件 4] 学习使用电位器和1602显示屏
- 自创算法——暴力自动机
- 先上两张图 搞起
- 使用JS播放HTML5中的音频
- 同步屏障CyclicBarrier
- 【新人杂记】sleep 和 wait 的区别
- linux下使用makefile问题集合
- 1038. Recover the Smallest Number