java版本
Open JDK 64-bit
jvm参数
-Xmx2g -Xms2g
基本类型
对象 32位大小
new Object() 16
new String("") 48
new String(new char[] {'1'}) 56
new String(new char[] {'1','2','3','4'}) 56
new String(new char[] {'1','2','3','4','5'}) 64
new Integer(0) 16
new Long(0) 24
new Float(0) 16
new Double(0) 24
new BigDecimal(0) 40
new Date() 24
new java.sql.Timestamp() 32
UUID 64
GregorianCalendar 448
new AtomicBoolean() 16
new AtomicInteger() 16
new AtomicLong() 24
容器
对象 大小
new TreeMap() 48
new HashMap() 136
new HashMap(1) 80
new Hashtable() 120
new Properties() 120
new LinkedHashMap() 120
new WeakHashMap() 144
new ConcurrentSkipListMap() 104
new ConcurrentHashMap() 224
new ConcurrentHashMap(1,0.75f,1) 168
new TreeSet() 64
new HashSet() 160
new LinkedHashSet() 200
new ArrayList() 80
new ArrayList(1) 48
new CopyOnWriteArrayList() 88
new CopyOnWriteArraySet() 104
new Vector() 88
new LinkedList() 32
new Stack() 88
new PriorityQueue() 96
new ConcurrentLinkedQueue() 48
数组
对象 大小
new byte[0] 16
new byte[1] 24
new byte[8] 24
new short[0] 16
new short[1] 24
new short[4] 24
new short[5] 32
new char[0] 16
new char[1] 24
new char[4] 24
new char[5] 32
new int[0] 16
new int[1] 24
new int[2] 24
new int[3] 32
new long[0] 16
new long[1] 24
new long[2] 32
new Object[0] 16
new Object[1] 24
new Object[2] 24
new Object[3] 32
—————————————————————
boolean 1
byte 1
short 2
char 2
int 4
float 4
long 8
double 8
new byte[8] 24
从jdk5开始,提供了Instrumentation API,它有一个叫做getObjectSize()的方法,但是,这个方法存在问题:不可以直接使用。必须要实现一个Instrumentation Agent,还得放到jar包里面。解决方案:在任何一个类里面声明一个"premain"方法,就可以把这个类做成是一个agent,jvm在启动的时候会调用premain()方法,同时会传递Instrumentation这个对象实例,要告诉jvm Instrumentation agent所在的类,需要把这个类打到jar包里面。
另外,在打包时候需要在MANIFEST.MF中写入三项值(注意包路径名改成自己的包名):
- Premain-class: xxx.yyy.zzz.SizeOfObject
- Can-Redefine-Classes: false
- Boot-Class-Path:
代码就是用的大神提供的sizeof方法。测试代码比较简单:
public class SizeTest {
public static void main(String[] args) {
byte[] b = new byte[2];
System.out.println("object:"+ SizeOfObject.sizeOf(new Object()));
System.out.println( "byte[2]"+SizeOfObject.sizeOf(b));
}
}
进入命令行,查看版本:

从Java SE 6u23之后的64位版本就默认打开了对象指针压缩。所以本机1.7也是,注意对比结果不同下面会有分析。
进度测试代码目录,并执行编译:javac *.java
打包,jar -cvfm size.jar MANIFEST.MF *

执行,分别对应启动指针压缩,关闭指针压缩。

分析不同:下面未开启情况: new byte[2]2*1+16+8=26+padding(8)=32,
针对开启情况: object header,未压缩前由一个native-sized mark word 8bytes加上一个class word 8bytes组成,共16bytes。采用压缩后,class word缩减为4bytes,现共占用12bytes;
2. reference类型,由8bytes缩减为4bytes;
3. 数组长度,由8bytes缩减为4bytes。byte[3][7], reference占用内存4byte,数组第1维长度为3,这样占用的总内存为4 * 3 + 12 = 24,所以byte[3][7]占用内存为24bytes。再如byte[7][3], reference占用内存4byte,数组第1维长度为7,这样占用的总内存为4 * 7 + 12 = 40,所以byte[7][3]占用内存为40bytes。
2. 在64位的系统中, 占用内存为: reference占用内存 * 数组第1维长度 +24(数组本身被当做reference占16bytes,数组长度占8bytes)。如:
byte[3][7], reference占用内存8byte,数组第1维长度为3,这样占用的总内存为8 * 3 + 24 = 48,所以byte[3][7]占用内存为48bytes。
************************学习笔记总结*******************************
1.同样的程序在不同环境下占用内存大小不一样,64位比32位大。
2,多维数组优化内存角度考虑:数组的一维尽可能小,这样占的内存小。
3.jdk1.6以后默认开启内存指针压缩,占的内存比以前未开启的要小。
就到这里吧,在考虑调优应该是jvm堆、栈那块知识了。另外整理吧。