目录

问题

代码实践

实验结果

Java对象内存布局

对象头:

实例数据:

对齐填充:

HashMap本身占用内存

Node占用内存

参考文章



本文内容来源于摘抄总结实践

问题

kv都是 int,一个 int 4 byte,就是100w * 8那就是8M,或者存储的是包装类 Integer ,一个 Integer 16 byte,那就是32 M 咯?

代码实践

通过java.lang.Runtime类中的freeMemory()方法来进行测试,输出freeMemory前,调用一次System.gc(),得出结论是百万键值对的HashMap占用大约69M空间。

package Java2;import java.util.HashMap;/*** @author ranbo* @version V1.0* @Title:* @Package Java2* @Description:* @date 2018/7/26 下午10:55*/
public class HashMapUseMemory {public static void main(String[] args) {double start = 0;double end = 0;System.gc();start = Runtime.getRuntime().freeMemory();  // 在java程序运行的过程的,内存总是慢慢的从操作系统那里挖的,基本上是用多少挖多少,但是java虚拟机100%的情况下是会稍微多挖一点的,// 这些挖过来而又没有用上的内存,实际上就是freeMemory()System.out.println("start: " + start);System.out.println("end: " + end);HashMap<Integer, Integer> hashMap = new HashMap<>();for (int i = 0; i < 1000000; i++) {hashMap.put(i, 128);   // value 为128 和 127 就是int和Integer的区别,(16 byte - 4 byte) * 100w就是 12 M的样子  IntegerCacheif(i % 10000 == 0) {end = Runtime.getRuntime().freeMemory();System.out.println("start: " + start);System.out.println("end: " + end);System.out.println("HashMap对象占内存:" + (end - start) + " byte");System.out.println("HashMap对象占内存:" + (end - start) / (1024 * 1024) + " M");}}end = Runtime.getRuntime().freeMemory();System.out.println("start: " + start);System.out.println("end: " + end);System.out.println("HashMap对象占内存:" + (end - start) + " byte");System.out.println("HashMap对象占内存:" + (end - start) / (1024 * 1024) + " M");System.out.println("----------清除了没有对象引用的对象");  // 即不可达对象System.gc(); // 清除了没有对象引用的对象,比如里面的临时变量,个人觉得 hash 也是end = Runtime.getRuntime().freeMemory();System.out.println("start: " + start);System.out.println("end: " + end);System.out.println("HashMap对象占内存:" + (end - start) + " byte");System.out.println("HashMap对象占内存:" + (end - start) / (1024 * 1024) + " M");}}}

实验结果

那接下来我们就来分析为啥会有这么多内存占用

Java对象内存布局

Java对象的内存布局包括:对象头(Header),实例数据(Instance Data)和补齐填充(Padding)。

对象头:

64位机器上,默认不开启指针压缩(-XX:-UseCompressedOops)的情况下,对象头占用12bytes,开启指针压缩(-XX:+UseCompressedOops)则占用16bytes。

实例数据:

原生类型(primitive type)的内存占用如下:

Primitive Type

Memory Required(bytes)

byte, boolean

1 byte

short, char

2 bytes

int, float

4 bytes

long, double

8 bytes

对象引用(reference)类型在64位机器上,关闭指针压缩时占用8bytes, 开启时占用4bytes。

对齐填充:

Java对象占用空间是8字节对齐的,即所有Java对象占用bytes数必须是8的倍数。例如,一个包含两个属性的对象:int和byte,并不是占用17bytes(12+4+1),而是占用24bytes(对17bytes进行8字节对齐)

HashMap本身占用内存

    /*** The table, initialized on first use, and resized as* necessary. When allocated, length is always a power of two.* (We also tolerate length zero in some operations to allow* bootstrapping mechanics that are currently not needed.)*/transient Node<K,V>[] table;/*** Holds cached entrySet(). Note that AbstractMap fields are used* for keySet() and values().*/transient Set<Map.Entry<K,V>> entrySet;/*** The number of key-value mappings contained in this map.*/transient int size;/*** The number of times this HashMap has been structurally modified* Structural modifications are those that change the number of mappings in* the HashMap or otherwise modify its internal structure (e.g.,* rehash).  This field is used to make iterators on Collection-views of* the HashMap fail-fast.  (See ConcurrentModificationException).*/transient int modCount;/*** The next size value at which to resize (capacity * load factor).** @serial*/// (The javadoc description is true upon serialization.// Additionally, if the table array has not been allocated, this// field holds the initial array capacity, or zero signifying// DEFAULT_INITIAL_CAPACITY.)int threshold;/*** The load factor for the hash table.** @serial*/final float loadFactor;

所以一个HashMap对象本身的大小为:

12(header) + 4(table reference) + 4(entrySet reference) + 4(size) + 4(modCount) + 4(threshold) + 8(loadFactor) + 4(keySet reference) + 4(values reference) = 48(bytes)

接着分析testMap实例在总共占用的内存大小。

Node占用内存

根据上面对HashMap原理的介绍,可知每对键值对对应一个Node对象。根据上面的Node的数据结构,一个Node对象的大小为:

     /*** Basic hash bin node, used for most entries.  (See below for* TreeNode subclass, and in LinkedHashMap for its Entry subclass.)*/static class Node<K,V> implements Map.Entry<K,V> {final int hash;final K key;V value;Node<K,V> next;Node(int hash, K key, V value, Node<K,V> next) {this.hash = hash;this.key = key;this.value = value;this.next = next;}}

12(header) + 4(hash reference) + 4(key reference) + 4(value reference) + 4(next pointer reference) = 28 (padding) -> 32(bytes)

加上Key和Value两个Integer对象,一个Node占用内存总大小为:32 + 2 * 16 = 64(bytes)

100w个就是 1000000 * 64

下面分析HashMap的Node数组的大小。

根据上面HashMap的原理可知,HashMap初为满足100w个node需要扩容到 1024 * 1024 * 2,这样乘以负载因子才会大于100w,所以Node[]占用的内存大小为:

Node[] = 16(header) + 1024 * 1024 * 2 * 4(Node reference) + 1000000 *64(Node)

所以,testMap占用的内存总大小为:

48(map itself) + (16 + (1024 * 1024 * 2 * 4) + 64 * 1000000)(Node[]) = = 72388672 byte

72388672 byte / (1024 *1024) = 69.03521728515625 M

参考文章

一个1000万HashMap,会占用多少空间内存?

Java对象内存占用分析

Java中HashMap结构自身占用的内存和Runtime类的freeMemory()等几个方法

HashMap put 一百万个 kv 都是 Int 类型的数据需要多少空间?相关推荐

  1. 人工智能数据标注都有哪些类型

    人工智能数据标注都有哪些类型 人工智能数据标注指的是,将非结构化数据转换成电脑可以识别理解的结构化数据. 例如,将下图中的车识别出来,人看到车的外轮廓是: 但是需要让电脑去识别认知这个图中的车,电脑需 ...

  2. 程序员收到阿里offer,提离职被怒:为年薪百万连兄弟都不做啦!

    热文推荐: 尘埃落定!清华才子王垠加入华为职级22,前阿里P10赵海平加入字节跳动,职级或为4+ 百度网盘"破解版",Pandownload开发者被抓 在当今社会,钱就是衡量一个人 ...

  3. 现在Python就业很难吗?百万程序员都在关心的问题

    这是我最近逛脉脉职言,看到的一则动态.我知道我们很多已经转行python或者即将转行python都要面对的一个问题–就业! 本文跟大家分享Python的几个主要发展和就业方向,给准备转行学习Pytho ...

  4. 大数据培训:生活中这些场景都用到了大数据

    来源:千锋大数据 一.什么是大数据 大数据(big data),指无法在一定时间范围内用常规软件工具进行捕捉.管理和处理的数据集合,需要新处理模式才能具有更强的决策力.洞察力和流程优化能力的海量.高增 ...

  5. 在远程调用别人接口的时候,传输参数一般都是String类型的字符串,改字符串可以是json格式的,也可以是xml格式的,那么问题来了

    在远程调用接口的时候,传输参数一般都是String类型的字符串,该字符串可以是json规则格式的,也可以是xml规则格式的,那么问题来了. 怎么将自己的对象,拼接成接口规定的格式?即将非格式化的数据( ...

  6. hive 插入数据映射到hbase_年薪50万都难招的大数据工程师,凭什么?

    回顾2018年,降薪.裁员.互联网寒冬似乎成为主旋律,那实际上资本市场萎缩了吗? 其实不然,2018年6月,蚂蚁金服还获得140亿融资,而热度较高的大数据行业,在2018年的融资额达到1273.1亿元 ...

  7. 元宇宙iwemeta: 重庆打造“数据之都”,拟成立重庆数据交易所

    重庆打造"数据之都",拟成立重庆数据交易所.重庆数据交易所,简称重数所. 重庆数据交易所,围绕确权难.定价难.互信难.入场难.监管难等关键共性难题,形成公共性数据资产交易所,提供数 ...

  8. C++对C的加强之C++中所有的变量和函数都必须有类型

    变量和函数都必须有类型 C++中所有的变量和函数都必须有类型 总结 C++中所有的变量和函数都必须有类型 /* C++中所有的变量和函数都必须有类型 C语言中的默认类型在C++中是不合法的 函数f的返 ...

  9. 计算机d盘给c盘,win10 c盘与d盘都是主分区如何将d盘空间分给c盘

    在安装win10系统的时候,用户都喜欢将硬盘分为多个主分区盘符,可是在使用过程中,发现win10系统中c盘空间越来越小,因此就想要将d盘空间分一些给c盘,那么win10系统c盘与d盘都是主分区时如何将 ...

  10. 有两个集合,两个集合都是10万个数据(已排序),判断B是不是A的子集,算法时间复杂度为Q(N)...

     有两个集合   集合A{1,7,19,21,55,100...}   集合B{7,22,100...}   两个集合都是10万个数据(已排序),要求写一个算法,判断B是不是A的子集,算法时间复杂度为 ...

最新文章

  1. 第三十二课.脉冲神经网络SNN
  2. awl 多线程SYN***工具0.2版,加了MAC伪装
  3. 华为AR28-31配置光纤接入
  4. 从虚拟化、统一映射和自动化看09年法规遵从趋势
  5. ios - 使用@try、catch捕获异常:
  6. linux系统硬盘数据恢复软件下载,Linux硬盘数据恢复软件
  7. Wince6 RIL层移植
  8. 关于mobile中datagrid的使用
  9. 解决xampp启动mysql失败
  10. 1 sqlserver修改表结构
  11. 入门级XML学习(三)
  12. python简单的爬虫实例
  13. 制造车间怎么推行5S管理?
  14. jdbc常见异常及错误解决办法汇总
  15. java 实现图片水印 文字水印
  16. 圆拟合Taubin fit 方法
  17. matlab7.1一直打不开,Matlab 7.1安装及打不开问题解决
  18. Java使用aspose批量将PDF转为word
  19. 气象站可以用计算机分析什么数据,多功能气象站有什么用
  20. 正确的-配置Tomcat环境变量

热门文章

  1. HRBU_20211119训练
  2. html固定页眉页脚,html-固定的页眉/页脚内容高度100%导致不希望的垂直滚动
  3. KVM Bridge 配置
  4. 硬盘设备出现“设备硬件出现致命错误,导致请求失败”怎么办?
  5. 全网最全面最精华的设计模式讲解,从程序员转变为工程师的第一步
  6. Matlab双缝干涉实验与牛顿环实验
  7. 题外话——第九届学生团体活动月开幕式感触
  8. VR开发2015年终总结
  9. PAT【L2-016】愿天下有情人都是失散多年的兄妹(dfs超详解)
  10. ElasticSearch全文搜索引擎-入门篇