ICode9

精准搜索请尝试: 精确搜索
首页 > 系统相关> 文章详细

【Java技术探索】各种类型对象占用内存情况分析(上)

2021-06-20 22:04:11  阅读:158  来源: 互联网

标签:oscimg Java 各种类型 占用 bytes 内存 https net png


# 内容简介 > **本文深入分析并验证了不同Java对象占用内存空间大小的情况。对于不同的jvm实现,Java对象占用的内存空间大小可能不尽相同,本文主要分析HotSpot jvm中的情况,实验环境为64位window10系统、JDK1.8**。 # 对象头 > **在64位机器上,默认不开启指针压缩(-XX:-UseCompressedOops)的情况下,对象头占用16bytes,开启指针压缩(-XX:+UseCompressedOops)则占用12bytes**。 # 实例数据 原生类型(primitive type)的内存占用如下: ![](https://oscimg.oschina.net/oscnet/up-7e273e6f7645ce2c42a780cc86e56c38287.png) > **对象引用(reference)类型在64位机器上,关闭指针压缩时占用8bytes, 开启时占用4bytes**。 # 对齐填充 > **Java对象占用空间是8字节对齐的,即所有Java对象占用bytes数必须是8的倍数。包含两个属性的对象:int和byte,并不是占用17bytes(12+4+1),而是占用24bytes(对17bytes进行8字节对齐)** # 对象内存占用(前提回顾) 首先根据以上的计算规则,进行一个简单的验证。使用下面的程序进行验证: ```java public class Test { public static void main(String[] args) throws InterruptedException { TestObject testObject = new TestObject(); Thread.sleep(600 * 1000); System.out.println(testObject); } } class TestObject { private int i; private double d; private char[] c; public TestObject() { this.i = 1; this.d = 1.0; this.c = new char[]{'a', 'b', 'c'}; } } ``` **TestObject对象有四个属性,分别为int, double, Byte, char[]类型**。在打开指针压缩(**-XX:+UseCompressedOops**)的情况下,在64位机器上,TestObject占用的内存大小应为: > **12(Header) + 4byte(int) + 8byte(double) + 4byte(reference) = 28 (bytes),加上4byte对齐(padding),最终的大小应为32bytes**。 ![](https://oscimg.oschina.net/oscnet/up-1239cde4c8b2318d11f86e5731f5ff86dca.png) 当指针压缩关闭时(-XX:-UseCompressedOops),在64位机器上,TestObject占用的内存大小应为: > **16(Header) + 4(int) + 8(double) + 8(reference) = 36 (bytes),4字节对齐后为 40 bytes。** ![](https://oscimg.oschina.net/oscnet/up-d1ef1835299e6154577edcf4bc93446cb3c.png) ## 包装类型 > 包装类(Boolean/Byte/Short/Character/Integer/Long/Double/Float)占用内存的大小等于**对象头大小加上底层基础数据类型**的大小。 包装类型的对象内存占用情况如下: ![](https://oscimg.oschina.net/oscnet/up-17bcdc4474c1591d9fcb2202344845a2373.png) ## 数组 > **64位机器上,数组对象的对象头占用24 bytes,启用压缩后占用16字节。比普通对象占用内存多是因为需要额外的空间存储数组的长度。** - 基础数据类型数组占用的空间包括**数组对象头**以及**基础数据类型数据占用的内存空间**。 - 对象数组中存放的是对象的引用,所以对象数组本身的大小=**数组对象头**+**length * 引用指针大小**,总大小为**对象数组本身大小+存放的数据的大小之和**。 ### 举两个例子: #### int[10]: > **开启压缩:16(12Byte(8[标记字段]+4[类型指针])+4[数组长度大小]) + 10(大小) * 4(32bit的整数类型) = 56 bytes;** ![](https://oscimg.oschina.net/oscnet/up-f69c2e6a4282609a587dea7411bf749ed63.png) > **关闭压缩:24(16Byte(8[标记字段]+8[类型指针])+4[数组长度大小]+4[padding]) + 10 * 4(32bit的整数类型) = 64bytes** ![](https://oscimg.oschina.net/oscnet/up-d61c7a6cdb05ed8a60b9949c0b973489f8b.png) #### new Integer[3]: ##### 关闭压缩: Integer数组本身:24(header) + 3 * **8(Integer reference)** = 48 bytes; > **总共:48 + 3 * 24(Integer) = 120 bytes**。 ![](https://oscimg.oschina.net/oscnet/up-c727b120592f6f8bb0b9a54e85977f1f199.png) ##### 开启压缩: > **Integer数组本身:16(header) + 3 * 4(Integer reference) = 28+4(padding) -> 32 (bytes)** > **总共:32 + 3 * 16(Integer)[12byte的对象头+4byte的引用reference] = 80 (bytes)** ![](https://oscimg.oschina.net/oscnet/up-9eae3e5193402969441f135400bcf8c7537.png) ## String > 在JDK1.7及以上版本中,String包含2个属性,一个用于存放字符串数据的char[], 一个int类型的hashcode, 部分源代码如下: ```java public final class String implements java.io.Serializable, Comparable, CharSequence { /** The value is used for character storage. */ private final char value[]; /** Cache the hash code for the string */ private int hash; // Default to 0 } ``` 因此,在关闭指针压缩时,一个String本身需要 **16(Header) + 8(char[] reference) + 4(int) = 32 bytes**。 > 除此之外,一个**char[]**占用**24byte(**其中有4byte的对齐padding**) + length * 2 bytes**(8字节对齐), 即一个String占用的内存空间大小为: **56** + **length * 2 bytes(char的18bit)** (8字节对齐)。 ### 举几个例子。 > 一个空字符串("")的大小应为:**56 + 0 * 2 bytes = 56 bytes**。 ![](https://oscimg.oschina.net/oscnet/up-1698188d4563b51bafa8a6f1b458aacff36.png) > **字符串"abc"的大小应为:56 + 3 * 2 = 62(8字节对齐)->64 (bytes)** ![](https://oscimg.oschina.net/oscnet/up-2d3fe21a7e785655d27a2cb8af3efa8b1d4.png) > **字符串"abcde"的大小应为:56 + 5 * 2 = 66->72 (bytes)** ![](https://oscimg.oschina.net/oscnet/up-9cc1f9adf51832c22f03b6ccc384f64c74a.png) > **字符串"abcde"在开启指针压缩时的大小为**: **String本身:12(Header) + 4(char[] reference) + 4(int hash) = 20(padding) -> 24 (bytes);** > **存储数据:16(char[] header) + 5 * 2 = 26(padding) -> 32 (bytes)** > **总共:24 + 32 = 56 (bytes)** ![](https://oscimg.oschina.net/oscnet/up-6420ae225fe3a58872f5a26e6f51630c0d7.png)

标签:oscimg,Java,各种类型,占用,bytes,内存,https,net,png
来源: https://blog.51cto.com/alex4dream/2928921

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有