Upload
oliver-lee
View
402
Download
8
Embed Size (px)
Citation preview
Java对象内存占⽤用
佐井@淘宝旅⾏行
主要内容• 内存理解
• Java基本类型内存占⽤用
• Java对象内存占⽤用
• Java数组内存占⽤用
• Java集合内存占⽤用
内存
1 byte
— — — — — — — —8 bits 7 6 5 4 3 2 1 0
——————————
—————————2 nibbles hi low
—————————————————————1 byte byte
1 byte 实际值
— — — — — — — —8 bits 1 1 0 0 1 0 1 0
——————————
—————————2 nibbles C A
—————————————————————1 byte CA
例⼦子:Java Class 表⽰示
魔数(Magic Number)
Class版本 (Minor+Major) 常量池信息
⼀一个连续的byte序列, 每个byte都有⼀一个确定的地址。
Memory � (*) �
Java中的数据类型
• 基本类型(non-objecs) boolean,byte,short,int,double…
• 对象new出来的都是对象
• 数组固定⼤大⼩小,最多2,147,483,648个元素
问题声明:本次讨论如果未特殊声明,默认为x64架构
装箱&基本类型?Q:Integer和int内存占⽤用⼤大⼩小⽐比例是多少?
a. 1 : 1 b. 1.33 : 1 c. 2 : 1 d. ?
字符串?Q:⼀一个8个字符的字符串占⽤用多少个byte?
a. 8b. 16 c. 28d. ?
更⼤大?更好?Q:HashSet与HashMap对⽐比?
a. 功能更少,占⽤用内存更少b. 功能更多,占⽤用内存更少c. ⼀一样⼀一样的d. ?
集合
Q:排序下列集合,假设默认构造⽅方法创建: ArrayList,HashSet,LinkedList,HashMap
基本类型—————————————
————type bytes—————————————
————byte 1boolean 1
char 2short 2float 4int 4
long 8double 8
—————————————————
了解Java Object
hotspot/src/share/vm/oops/oop.hpp
Layout of Java Object
• hashCode范围没有定义那么⼤大 !
• 64位JVM Object Header内存浪费:26/64=40%
关于对象指针• -XX:+UseCompressedOops
• 默认开启条件
• 是64位JVM,并且不是client VM
• Java堆的最⼤大⼤大⼩小不⼤大于⼀一个阈值
• 没有⼿手动设定过UseCompressedOops参数的值
• 没有使⽤用Garbage-First (G1) GC
接下来讨论默认开启UseCompressedOops
对象内存占⽤用java.lang.Integer 16byte
header12byte
int4 byte
java.lang.Long20byte
header12byte
int8 byte
Integer : int = 16:4 = 4:1
20byte 是否正确?
对象对⻬齐
对象对⻬齐:8-XX:ObjectAlignmentInBytes=32
-XX:ObjectAlignmentInBytes=4 ??
error: ObjectAlignmentInBytes=4 must be greater or equal 8
对象内存占⽤用java.lang.Long24byte
header12byte
int8 byte
alignment4 byte
java.lang.Boolean16byte
header12byte
boolean1 byte
alignment3 byte
空间浪费16/24=66%
空间浪费15/16=93% !!!
hotspot/src/share/vm/oops/arrayOop.hpp
⽐比Java对象多⼀一个“⻓长度”
数组布局
8-chars String
header12byte
fields12 byte
pointer4byte
alignment4 byte
chars
header16byte
header16byte
• 8个字符的字符串占64byte
• 浪费了75%空间
集合内存占⽤用• HashMap
!• HashSet
!• ArrayList
!• LinkedList
HashMap
• transient java.util.HashMap.Entry[] table; //4+(16+4*16) • transient int size;//4 • int threshold;//4 • final float loadFactor;//4 • transient volatile int modCount;//4 • private transient
java.util.Set<java.util.Map.Entry<K,V>> entrySet;//4 • transient volatile java.util.Set<K> keySet;//4 • transient volatile java.util.Collection<V> values;//4
total=12+4*8+16+4*16=128byte
default:16
HashSet
• private transient java.util.HashMap<E,java.lang.Object> map
total=12+4+128=144byte
default:16
ArrayList
• private transient java.lang.Object[] elementData; • private int size;
total=(12+4+4+4)+16+4*10=80byte
default:10
LinkList
• private transient java.util.LinkedList.Entry<E> header;
• E element;
• Entry<E> next;
• Entry<E> previous;
• private transient int size;
default:0
total=(12+4+4+4)+12+4*3=48byte
LinkedList>ArrayList>HashMap>HashSet
Q:排序,假设默认构造⽅方法创建,并添加两个元素: ArrayList,HashSet,LinkedList,HashMap
Homework ;)
总结• JVM hashCode 占⽤用 32:25byte,64:31byte
• 对象对⻬齐,会浪费空间
• ⼩小字符串,空间浪费很⼤大
• 集合默认占⽤用⼤大量空间
• 64位JVM⽐比32位平均浪费20%-30%空间
• Java ⼀一切皆对象
• 尽量⽤用基本类型,不⽤用装箱类型(heap,gc)
QA