阅读本文大概需要 8.5 分钟。
# 计算机的存储单位
# 换算关系
<span class="code-snippet_outer" style="max-width: 1000%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span class="code-snippet__meta" style="max-width: 1000%;">1B(Byte</span> <span class="code-snippet__string" style="max-width: 1000%;">字节) = 8bit(位)</span></span>
<span class="code-snippet_outer" style="max-width: 1000%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span class="code-snippet__attr" style="max-width: 1000%;">1KB</span> = <span class="code-snippet__string" style="max-width: 1000%;">1024B</span></span>
<span class="code-snippet_outer" style="max-width: 1000%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span class="code-snippet__attr" style="max-width: 1000%;">1MB</span> = <span class="code-snippet__string" style="max-width: 1000%;">1024KB</span></span>
<span class="code-snippet_outer" style="max-width: 1000%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span class="code-snippet__attr" style="max-width: 1000%;">1GB</span> = <span class="code-snippet__string" style="max-width: 1000%;">1024MB</span></span>
<span class="code-snippet_outer" style="max-width: 1000%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span class="code-snippet__attr" style="max-width: 1000%;">1TB</span> = <span class="code-snippet__string" style="max-width: 1000%;">1024GB</span></span>
# Java中对象占用多少内存
# Java基本类型
# Java引用类型
# 对象在内存中的布局
# 对象头
运行时数据:存储了对象自身运行时的数据,例如哈希码、GC分代的年龄、锁状态标志、线程持有的锁、偏向线程ID等等。这部分数据在32位和64位的虚拟机中分别为32bit和64bit
类型指针:对象指向它的类元数据的指针,虚拟机通过这个指针来确定这个对象是哪个类的实例。如果对象是一个Java数组的话,那么对象头中还必须有一块用于记录数组长度的数据(占用4个字节)。所以这是一个指针,默认JVM对指针进行了压缩,用4个字节存储。
我们以虚拟机为64位的机器为例,那么对象头占用的内存是8(运行时数据)+4(类型指针)=12Byte。如果是数组的话那么就是16Byte
# 实例数据
从父类中继承下来的变量也是需要进行计算的
# 对齐填充
实战演练
<span class="code-snippet_outer" style="max-width: 1000%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span class="code-snippet__keyword" style="max-width: 1000%;">class</span> <span class="code-snippet__title" style="max-width: 1000%;">Animal</span>{</span>
<span class="code-snippet_outer"><br></span>
<span class="code-snippet_outer" style="max-width: 1000%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span class="code-snippet__keyword" style="max-width: 1000%;">private</span> <span class="code-snippet__keyword" style="max-width: 1000%;">int</span> age;</span>
<span class="code-snippet_outer"><br></span>
<span class="code-snippet_outer" style="max-width: 1000%;box-sizing: border-box !important;overflow-wrap: break-word !important;">}</span>
<span class="code-snippet_outer" style="max-width: 1000%;box-sizing: border-box !important;overflow-wrap: break-word !important;">--Gradle</span>
<span class="code-snippet_outer" style="max-width: 1000%;box-sizing: border-box !important;overflow-wrap: break-word !important;">compile 'org.openjdk.jol:jol-core:0.9'</span>
<span class="code-snippet_outer"><br></span>
<span class="code-snippet_outer" style="max-width: 1000%;box-sizing: border-box !important;overflow-wrap: break-word !important;">--Maven</span>
<span class="code-snippet_outer" style="max-width: 1000%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><<span class="code-snippet__name" style="max-width: 1000%;">dependency</span>></span>
<span class="code-snippet_outer" style="max-width: 1000%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span class="code-snippet__tag" style="max-width: 1000%;"><<span class="code-snippet__name" style="max-width: 1000%;box-sizing: border-box !important;overflow-wrap: break-word !important;">groupId</span>></span>org.openjdk.jol<span class="code-snippet__tag" style="max-width: 1000%;"></<span class="code-snippet__name" style="max-width: 1000%;box-sizing: border-box !important;overflow-wrap: break-word !important;">groupId</span>></span></span>
<span class="code-snippet_outer" style="max-width: 1000%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span class="code-snippet__tag" style="max-width: 1000%;"><<span class="code-snippet__name" style="max-width: 1000%;box-sizing: border-box !important;overflow-wrap: break-word !important;">artifactId</span>></span>jol-core<span class="code-snippet__tag" style="max-width: 1000%;"></<span class="code-snippet__name" style="max-width: 1000%;box-sizing: border-box !important;overflow-wrap: break-word !important;">artifactId</span>></span></span>
<span class="code-snippet_outer" style="max-width: 1000%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span class="code-snippet__tag" style="max-width: 1000%;"><<span class="code-snippet__name" style="max-width: 1000%;box-sizing: border-box !important;overflow-wrap: break-word !important;">version</span>></span>0.9<span class="code-snippet__tag" style="max-width: 1000%;"></<span class="code-snippet__name" style="max-width: 1000%;box-sizing: border-box !important;overflow-wrap: break-word !important;">version</span>></span></span>
<span class="code-snippet_outer" style="max-width: 1000%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></<span class="code-snippet__name" style="max-width: 1000%;">dependency</span>></span>
<span class="code-snippet_outer" style="max-width: 1000%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span class="code-snippet__keyword" style="max-width: 1000%;">public</span> <span class="code-snippet__keyword" style="max-width: 1000%;">class</span> <span class="code-snippet__title" style="max-width: 1000%;">AboutObjectMemory</span> {</span>
<span class="code-snippet_outer"><br></span>
<span class="code-snippet_outer" style="max-width: 1000%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span class="code-snippet__function" style="max-width: 1000%;"><span class="code-snippet__keyword" style="max-width: 1000%;box-sizing: border-box !important;overflow-wrap: break-word !important;">public</span> <span class="code-snippet__keyword" style="max-width: 1000%;box-sizing: border-box !important;overflow-wrap: break-word !important;">static</span> <span class="code-snippet__keyword" style="max-width: 1000%;box-sizing: border-box !important;overflow-wrap: break-word !important;">void</span> <span class="code-snippet__title" style="max-width: 1000%;box-sizing: border-box !important;overflow-wrap: break-word !important;">main</span>(<span class="code-snippet__params" style="max-width: 1000%;box-sizing: border-box !important;overflow-wrap: break-word !important;">String[] args</span>)</span> {</span>
<span class="code-snippet_outer" style="max-width: 1000%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> System.<span class="code-snippet__keyword" style="max-width: 1000%;">out</span>.print(ClassLayout.parseClass(Animal.class).toPrintable());</span>
<span class="code-snippet_outer" style="max-width: 1000%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> }</span>
<span class="code-snippet_outer" style="max-width: 1000%;box-sizing: border-box !important;overflow-wrap: break-word !important;">}</span>
<span class="code-snippet_outer" style="max-width: 1000%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span class="code-snippet__meta" style="max-width: 1000%;">aboutjava.other.Animal</span> <span class="code-snippet__string" style="max-width: 1000%;">object internals:</span></span>
<span class="code-snippet_outer" style="max-width: 1000%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span class="code-snippet__attr" style="max-width: 1000%;">OFFSET</span> <span class="code-snippet__string" style="max-width: 1000%;">SIZE TYPE DESCRIPTION VALUE</span></span>
<span class="code-snippet_outer" style="max-width: 1000%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span class="code-snippet__attr" style="max-width: 1000%;">0</span> <span class="code-snippet__string" style="max-width: 1000%;">12 (object header) N/A</span></span>
<span class="code-snippet_outer" style="max-width: 1000%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span class="code-snippet__attr" style="max-width: 1000%;">12</span> <span class="code-snippet__string" style="max-width: 1000%;">4 int Animal.age N/A</span></span>
<span class="code-snippet_outer" style="max-width: 1000%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span class="code-snippet__attr" style="max-width: 1000%;">Instance</span> <span class="code-snippet__string" style="max-width: 1000%;">size: 16 bytes</span></span>
<span class="code-snippet_outer" style="max-width: 1000%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span class="code-snippet__attr" style="max-width: 1000%;">Space</span> <span class="code-snippet__string" style="max-width: 1000%;">losses: 0 bytes internal + 0 bytes external = 0 bytes total</span></span>
# String占用多少内存
我们先自己进行分析一下。在String类中有两个属性,其中对象头固定了是12字节,int是4字节,char[]数组其实在这里相当于引用对象存的,所以存的是地址,因此占用4个字节,所以大小为对象头12Byte+实例数据8Byte+填充数据4Byte=24Byte这里的对象头和实例数据加起来不是8的倍数,所以需要填充数据进行填充。
<span class="code-snippet_outer" style="max-width: 1000%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span class="code-snippet__keyword" style="max-width: 1000%;">private</span> final <span class="code-snippet__keyword" style="max-width: 1000%;">char</span> <span class="code-snippet__keyword" style="max-width: 1000%;">value</span>[];</span>
<span class="code-snippet_outer"><br></span>
<span class="code-snippet_outer" style="max-width: 1000%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span class="code-snippet__keyword" style="max-width: 1000%;">private</span> <span class="code-snippet__keyword" style="max-width: 1000%;">int</span> hash; <span class="code-snippet__comment" style="max-width: 1000%;">// Default to 0</span></span>
<span class="code-snippet_outer" style="max-width: 1000%;box-sizing: border-box !important;overflow-wrap: break-word !important;">java.lang.String <span class="code-snippet__keyword" style="max-width: 1000%;">object</span> internals:</span>
<span class="code-snippet_outer" style="max-width: 1000%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> OFFSET SIZE TYPE DESCRIPTION VALUE</span>
<span class="code-snippet_outer" style="max-width: 1000%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span class="code-snippet__number" style="max-width: 1000%;">0</span> <span class="code-snippet__number" style="max-width: 1000%;">12</span> (<span class="code-snippet__keyword" style="max-width: 1000%;">object</span> header) N/A</span>
<span class="code-snippet_outer" style="max-width: 1000%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span class="code-snippet__number" style="max-width: 1000%;">12</span> <span class="code-snippet__number" style="max-width: 1000%;">4</span> <span class="code-snippet__keyword" style="max-width: 1000%;">char</span>[] String.<span class="code-snippet__keyword" style="max-width: 1000%;">value</span> N/A</span>
<span class="code-snippet_outer" style="max-width: 1000%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span class="code-snippet__number" style="max-width: 1000%;">16</span> <span class="code-snippet__number" style="max-width: 1000%;">4</span> <span class="code-snippet__keyword" style="max-width: 1000%;">int</span> String.hash N/A</span>
<span class="code-snippet_outer" style="max-width: 1000%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span class="code-snippet__number" style="max-width: 1000%;">20</span> <span class="code-snippet__number" style="max-width: 1000%;">4</span> (loss due to the next <span class="code-snippet__keyword" style="max-width: 1000%;">object</span> alignment)</span>
<span class="code-snippet_outer" style="max-width: 1000%;box-sizing: border-box !important;overflow-wrap: break-word !important;">Instance size: <span class="code-snippet__number" style="max-width: 1000%;">24</span> bytes</span>
# 用List存储对象
<span class="code-snippet_outer" style="max-width: 1000%;box-sizing: border-box !important;overflow-wrap: break-word !important;">List<Animal> animals = <span class="code-snippet__keyword" style="max-width: 1000%;">new</span> ArrayList<>(<span class="code-snippet__number" style="max-width: 1000%;">20000000</span>);</span>
<span class="code-snippet_outer" style="max-width: 1000%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span class="code-snippet__keyword" style="max-width: 1000%;">for</span> (<span class="code-snippet__keyword" style="max-width: 1000%;">int</span> i = <span class="code-snippet__number" style="max-width: 1000%;">0</span>; i < <span class="code-snippet__number" style="max-width: 1000%;">20000000</span>; i++) {</span>
<span class="code-snippet_outer" style="max-width: 1000%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> Animal animal = <span class="code-snippet__keyword" style="max-width: 1000%;">new</span> Animal();</span>
<span class="code-snippet_outer" style="max-width: 1000%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> animals.<span class="code-snippet__keyword" style="max-width: 1000%;">add</span>(animal);</span>
<span class="code-snippet_outer" style="max-width: 1000%;box-sizing: border-box !important;overflow-wrap: break-word !important;">}</span>
注意这里我是直接将集合的大小初始化为了二千万的大小,所以程序在正常启动的时候占用内存是100+MB,正常程序启动仅仅占用30+MB的,所以多出来的60+MB正好是我们初始化的数组的大小。至于为什么要初始化大小的原因就是为了消除集合在扩容时对我们观察结果的影响
<span class="code-snippet_outer" style="max-width: 1000%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span class="code-snippet__keyword" style="max-width: 1000%;">class</span> <span class="code-snippet__title" style="max-width: 1000%;">Animal</span>{</span>
<span class="code-snippet_outer"><br></span>
<span class="code-snippet_outer" style="max-width: 1000%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span class="code-snippet__keyword" style="max-width: 1000%;">private</span> <span class="code-snippet__keyword" style="max-width: 1000%;">int</span> age;</span>
<span class="code-snippet_outer" style="max-width: 1000%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span class="code-snippet__keyword" style="max-width: 1000%;">private</span> <span class="code-snippet__keyword" style="max-width: 1000%;">int</span> age1;</span>
<span class="code-snippet_outer" style="max-width: 1000%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span class="code-snippet__keyword" style="max-width: 1000%;">private</span> <span class="code-snippet__keyword" style="max-width: 1000%;">int</span> age2;</span>
<span class="code-snippet_outer" style="max-width: 1000%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span class="code-snippet__keyword" style="max-width: 1000%;">private</span> <span class="code-snippet__keyword" style="max-width: 1000%;">int</span> age3;</span>
<span class="code-snippet_outer" style="max-width: 1000%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span class="code-snippet__keyword" style="max-width: 1000%;">private</span> <span class="code-snippet__keyword" style="max-width: 1000%;">int</span> age4;</span>
<span class="code-snippet_outer"><br></span>
<span class="code-snippet_outer" style="max-width: 1000%;box-sizing: border-box !important;overflow-wrap: break-word !important;">}</span>
# 用Map存储对象
<span class="code-snippet_outer" style="max-width: 1000%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span class="code-snippet__keyword" style="max-width: 1000%;">static</span> <span class="code-snippet__class" style="max-width: 1000%;"><span class="code-snippet__keyword" style="max-width: 1000%;box-sizing: border-box !important;overflow-wrap: break-word !important;">class</span> <span class="code-snippet__title" style="max-width: 1000%;box-sizing: border-box !important;overflow-wrap: break-word !important;">Node</span><<span class="code-snippet__title" style="max-width: 1000%;box-sizing: border-box !important;overflow-wrap: break-word !important;">K</span>,<span class="code-snippet__title" style="max-width: 1000%;box-sizing: border-box !important;overflow-wrap: break-word !important;">V</span>> <span class="code-snippet__keyword" style="max-width: 1000%;box-sizing: border-box !important;overflow-wrap: break-word !important;">implements</span> <span class="code-snippet__title" style="max-width: 1000%;box-sizing: border-box !important;overflow-wrap: break-word !important;">Map</span>.<span class="code-snippet__title" style="max-width: 1000%;box-sizing: border-box !important;overflow-wrap: break-word !important;">Entry</span><<span class="code-snippet__title" style="max-width: 1000%;box-sizing: border-box !important;overflow-wrap: break-word !important;">K</span>,<span class="code-snippet__title" style="max-width: 1000%;box-sizing: border-box !important;overflow-wrap: break-word !important;">V</span>> </span>{</span>
<span class="code-snippet_outer" style="max-width: 1000%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span class="code-snippet__keyword" style="max-width: 1000%;">final</span> <span class="code-snippet__keyword" style="max-width: 1000%;">int</span> hash;</span>
<span class="code-snippet_outer" style="max-width: 1000%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span class="code-snippet__keyword" style="max-width: 1000%;">final</span> K key;</span>
<span class="code-snippet_outer" style="max-width: 1000%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> V value;</span>
<span class="code-snippet_outer" style="max-width: 1000%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> Node<K,V> next;</span>
<span class="code-snippet_outer" style="max-width: 1000%;box-sizing: border-box !important;overflow-wrap: break-word !important;">}</span>
<span class="code-snippet_outer" style="max-width: 1000%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span class="code-snippet__built_in" style="max-width: 1000%;">Map</span><Animal,Animal> map</span>
<span class="code-snippet_outer" style="max-width: 1000%;box-sizing: border-box !important;overflow-wrap: break-word !important;">Map<Animal,Animal> <span class="code-snippet__built_in" style="max-width: 1000%;">map</span> = <span class="code-snippet__keyword" style="max-width: 1000%;">new</span> HashMap<>(<span class="code-snippet__number" style="max-width: 1000%;">20000000</span>);</span>
<span class="code-snippet_outer" style="max-width: 1000%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span class="code-snippet__keyword" style="max-width: 1000%;">for</span> (<span class="code-snippet__keyword" style="max-width: 1000%;">int</span> i = <span class="code-snippet__number" style="max-width: 1000%;">0</span>; i < <span class="code-snippet__number" style="max-width: 1000%;">20000000</span>; i++) {</span>
<span class="code-snippet_outer" style="max-width: 1000%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span class="code-snippet__built_in" style="max-width: 1000%;">map</span>.put(<span class="code-snippet__keyword" style="max-width: 1000%;">new</span> Animal(),<span class="code-snippet__keyword" style="max-width: 1000%;">new</span> Animal());</span>
<span class="code-snippet_outer" style="max-width: 1000%;box-sizing: border-box !important;overflow-wrap: break-word !important;">}</span>
数组占用内存大小:我们先来计算一下数组占了多少,这里有个小知识点,在HashMap中初始化大小是按照2的倍数来的,比如你定义了大小为60,那么系统会给你初始化大小为64。所以我们定义为二千万,系统其实是会给我们初始化为33554432,所以此时仅仅HashMap中数组就占用了将近132MB
数据占用内存大小:我们上面计算了一个Node节点占用了64Byte,那么两千万条数据就占用了1280MB
# 总结
推荐阅读:
推荐 IntelliJ IDEA 特别“养眼”的主题插件,这几款超赞,总有一款适合你!
内容包含Java基础、JavaWeb、MySQL性能优化、JVM、锁、百万并发、消息队列、高性能缓存、反射、Spring全家桶原理、微服务、Zookeeper、数据结构、限流熔断降级……等技术栈!
⬇戳阅读原文领取! 朕已阅
文章收集整理于网络,请勿商用,仅供个人学习使用,如有侵权,请联系作者删除,如若转载,请注明出处:http://www.cxyroad.com/2069.html