查看原文
其他

一千万个身份证号的内存占用

ImportNew 2022-09-23

The following article is from 程序员阿水 Author 阿水

(给ImportNew加星标,提高Java技能)

作者:阿水

一千万个身份证号的内存占用


前些时间和一个小朋友聊一些技术的内容,我让他回去验证一下一千万个身份证号在java中要耗费多少内存,他写了个程序,得出来的结论是599MB,我掐指一算,如果通过数学推算的话,差了100多M,于是就和他赌10块钱,谁输谁给十块钱。这篇贴子就是为了要赚那10块钱。

这位同学的代码是这么写的

有两个问题

1.代码不太好看,标量命名a,b啥的2.for循环里是用同一个变量名来引用String对象,我判断他这么写的目的是避免再拿一个数组来存放的话,数组的内存占用就会带来误差,但是这么写的话就会引出GC的影响。

不过我不是低估了这个小朋友,他说他把新生代内存调到1G了,而且加了-XX:+PrintGCDetails参数,从日志来看,没有进行GC。

这个解释确实合情合理,让我竟无语凝噎。


到这份上了,那就来验证吧。

数学推算


1.在java中,所有对象的内存占用都会是8个字节的倍数,如果少于8个字节的倍数,则向上对齐到8的倍数。

2.身份证是18位,在内存中是以char数组存储,一个空的char数组本身要16个字节,一个char是2个字节,所以是16+18*2=52个字节。•char数组本身也是一个特殊的对象,对象头是8个字节,外加一个数组长度是int类型,4个字节,一共12个字节,不是8的倍数,向上对齐到16。

3.如果数组最终内存占用字节数不是8的倍数,则向上对齐到8的倍数,52不是8的倍数,则向上取56,占用56个字节。

4.一个空String是24个字节,加上char数组的56个字节=80个字节,是8的倍数。

5.1000万个身份证号,读到内存中,是1000万个String,总内存数是80*1000万字节=762.94M。

6.如果嫌麻烦,也可以用这个速算公式

String对象的最小内存占用 (bytes) = 8 * (int) ((((char数量 * 2) + 45) / 8

实验推算


基于数学得出来的是理论值,而且对于JVM里内存对象的占用,要做很深入的研究才能完全掌握,比如不同的机器、操作系统、jdk、jvm参数配置等等,都会影响到内存的占用。数学推算可做为一个合理的值范围,不会出现大的偏差,最好还是通过实验来验证。

char数组的真实内存情况


1.通过jps获得进程ID2.通过jamp导出对应进程的内存信息3.通过MAT工具分析char数组的内存情况


基于上图,我们选出一些常规值进行分析

•char[0]=16字节•char[2]=24字节•char[8]=32字节•char[13] =48字节•char[19] =56字节•char[36] =88字节•char[348] =712字节•char[14305] =28632字节

我们在写程序和排查问题时,很难说所有的问题,你都有相应的知识储备。在解决问题时,最重要的点是思路,结合我们已有的知识,从问题发现规律,理清头绪。以上面char数组的内存情况来分析,我们可以有以下思路

1.char是两个字节,这是java基础知识

2.即便是一个空的char数组,它也要16个字节

3.char[2]比char[0]多8个字节,而不是4个字节,为什么?

4.为什么所有的内存占用都是8的倍数,不管怎么样都是8的倍数,这是不是造成char[2]比char[0]多8个字节的原因,JVM有内存对齐机制

结论:char数组的内存占用=16+数组长度*2,如果最终结果不是8的倍数,则对齐到8的倍数。

String也可以用同样的方式来推导。

直接代码验证


• 空String数组,size为1000万,内存消耗为55728720字节

• String数组,内有1000万身份证号,内存消耗为841801640字节

• 二者相减,得786,072,920字节,等于750MB,与数学推算的762MB误差在2%以内。

后记


1.以上结论和推算都是基于jdk1.8.0_92,不同版本可能会有差别。

2.分析问题就和做数独一样,已知5个数,要把所有的数字解出来,中间可能需要试错。

3.学习的好处有两点

•知识面更广,就相当于拿到了一个简单的数独,81个数,已经填充了78个数了,你只需要解三个数就行


•你分析问题的思路会更解析,你有更多解数独的套路,顺着这些套路就可以一步步解答出来


推荐阅读  点击标题可跳转

当前疫情下火爆的直播应用,你了解背后的技术架构吗?

Java内存模型之可见性(填坑之路)

这里的字体用 12 号字体;


看完本文有收获?请转发分享给更多人

关注「ImportNew」,提升Java技能

好文章,我在看❤️

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存