前一段时间在看关于如何测定JVM中对象占用的内存,涉及到JVM堆中对象结构相关知识。
在网上看到一篇比较不错的文章,分享出来,希望对看到的人有所帮助。
---------------------------------
原文地址:http://www.javamex.com/tutorials/memory/object_memory_usage.shtml
在JVM堆中,每个对象由四个域构成:
1、对象头,占用很少的字节,表述Object当前状态的信息:
“对象头”的作用是用来记录一个对象的实例名字、ID和实例状态(例如,当前实例是否“可到达”,或者当前锁的状态等等)。
注:java在64bit模式下开启指针压缩,比32bit模式下头部会大4byte(_mark区域变成8byte,_class区域被压缩),即12字节。
如果没有开启指针压缩,头部会大8byte(_mark和_class都会变成8byte),即16字节。
jdk1.6参数-XX:+UseCompressedOops(指针压缩),在32G内存下默认会自动开启这个参数。
2、基本类型域占用的空间(原生域指int、boolean、short等):
boolean、byte占用1 byte,char、short占用2 bytes,int、float占用4bytes,long、double占用 8 bytes。
3、引用类型域占用的空间(引用类型域指 其他对象的引用,每个引用占用4个字节):
每个引用类型占用4bytes。
注:对于组合对象(比如String对象)而言,它不会把“被组合”的对象(比如:String中的char[]数组对象)作为自身空间,而是开辟一个引用类型空间来引用组合对象。组合关系是一种对象之间的相互引用,引用和被引用的对象之间相互分离的。在物理空间上,避免了一个对象和其成员对象在空间上必须连续的问题,而是一种逻辑上的Link。同样,被引用对象同样以8字节的倍数进行对齐。
4、填充物占用的空间:
在Hotspot中,每个对象占用的总空间是以8的倍数计算的,对象占用总空间(对象头+声明变量)不足8的倍数时候,自动补齐。而这些被填充的空间,我们可以称它为“填充物”。
注:对象采用8字节对齐的方式是不论32bit还是64bit都是一样的。
另外,如果对象是数组:则至少占用12字节(多出4个字节保存数组长度),同时数组也会以8字节自动补齐。
意义:
现在了解了JVM堆中对象的结构,就能在日常编程中对创建的对象估算其占用内存大小,以便进行优化。
例如:
1、现在有500个字节存入数组,可以写作
byte[] bytes = new byte[500]; //每个元素存储为一个byte.
或者
Byte[] bytes = new Byte[500]; //每个元素存储为一个Byte.
(1)首先计算一下new byte[500];占用内存大小:
8+4+1*500 = 512 byte
前12个字节是数组中8byte的空Object和4byte的数组长度,数组中每个元素占用1byte。
(2)然后计算new Byte[500];占用内存大小:
8+4+4*500+16*500=10012 byte -> 对齐 = 10016 byte
前12个字节是数组中8byte的空Object和4byte的数组长度,数组中包含500个Byte的引用(4*500),同时由于
每个元素都是Byte对象,共500个(16*500,一个Byte对象要以8字节对齐,所以为16byte)。
以上结果都经过SizeOf工具验证,同时可以参考我的blog:
使用SizeOf测定JVM中对象占用内存 http://shensy.iteye.com/blog/1765760
结论:使用byte数组存储占用内存0.5k,使用Byte数组存储占用内存近10k。
2、编程时,能用Boolean.TRUE或FALSE就不要用new Boolean(),能用Integer.valueOf的时候就不要用new Integer(),其它各数据类型也都如此。原因是这些方法会存储一部分数值放在一块共享内存区域作为缓存使用。详解请见我的blog:
JVM对象占用内存计算工具--SizeOf源码分析 http://shensy.iteye.com/blog/1858987
结束语:
理解了JVM堆中对象结构,对于日常Java编程中内存优化会有很大帮助。
相关推荐
Java是一种广泛使用的面向对象的编程语言,由Sun Microsystems公司于1995年5月正式发布。它的设计目标是“一次编写,到处运行(Write Once, Run Anywhere)”,这意味着开发者可以使用Java编写应用程序,并在支持...
Java中的并发编程机制包括线程、同步、锁等,以及java.util.concurrent包提供的高级并发功能。 异常处理: Java通过异常处理机制提供了一种结构化的错误处理方式,允许程序在遇到错误时优雅地恢复或终止。 Java新特性...
Java是一种广泛使用的面向对象的编程语言,由Sun Microsystems公司于1995年5月正式发布。它的设计目标是“一次编写,到处运行(Write Once, Run Anywhere)”,这意味着开发者可以使用Java编写应用程序,并在支持...
包括但不仅限于链表、栈,队列,树,堆,图等经典数据结构及其他经典基础算法(如排序等)... Java是一种广泛使用的面向对象的编程语言,由Sun Microsystems公司于1995年5月正式发布。它的设计目标是“一次编写,...
Java是一种广泛使用的面向对象的编程语言,由Sun Microsystems公司于1995年5月正式发布。它的设计目标是“一次编写,到处运行(Write Once, Run Anywhere)”,这意味着开发者可以使用Java编写应用程序,并在支持...
深入理解JVM内存模型、垃圾收集等底层知识 熟悉主流框架的设计思想和运行原理 掌握数据库、缓存、分布式系统等企业级开发技能 拓展视野,了解大数据、人工智能等前沿领域 综上所述,这本Java面试书籍旨在为广大Java...
Java是一种广泛使用的面向对象的编程语言,由Sun Microsystems公司于1995年5月正式发布。它的设计目标是“一次编写,到处运行(Write Once, Run Anywhere)”,这意味着开发者可以使用Java编写应用程序,并在支持...
Java是一种广泛使用的面向对象的编程语言,由Sun Microsystems公司于1995年5月正式发布。它的设计目标是“一次编写,到处运行(Write Once, Run Anywhere)”,这意味着开发者可以使用Java编写应用程序,并在支持...
Java是一种广泛使用的面向对象的编程语言,由Sun Microsystems公司于1995年5月正式发布。它的设计目标是“一次编写,到处运行(Write Once, Run Anywhere)”,这意味着开发者可以使用Java编写应用程序,并在支持...
Java是一种广泛使用的面向对象的编程语言,由Sun Microsystems公司于1995年5月正式发布。它的设计目标是“一次编写,到处运行(Write Once, Run Anywhere)”,这意味着开发者可以使用Java编写应用程序,并在支持...
Java是一种广泛使用的面向对象的编程语言,由Sun Microsystems公司于1995年5月正式发布。它的设计目标是“一次编写,到处运行(Write Once, Run Anywhere)”,这意味着开发者可以使用Java编写应用程序,并在支持...
Java是一种广泛使用的面向对象的编程语言,由Sun Microsystems公司于1995年5月正式发布。它的设计目标是“一次编写,到处运行(Write Once, Run Anywhere)”,这意味着开发者可以使用Java编写应用程序,并在支持...
Java是一种广泛使用的面向对象的编程语言,由Sun Microsystems公司于1995年5月正式发布。它的设计目标是“一次编写,到处运行(Write Once, Run Anywhere)”,这意味着开发者可以使用Java编写应用程序,并在支持...
Java是一种广泛使用的面向对象的编程语言,由Sun Microsystems公司于1995年5月正式发布。它的设计目标是“一次编写,到处运行(Write Once, Run Anywhere)”,这意味着开发者可以使用Java编写应用程序,并在支持...
Java是一种广泛使用的面向对象的编程语言,由Sun Microsystems公司于1995年5月正式发布。它的设计目标是“一次编写,到处运行(Write Once, Run Anywhere)”,这意味着开发者可以使用Java编写应用程序,并在支持...
Java是一种广泛使用的面向对象的编程语言,由Sun Microsystems公司于1995年5月正式发布。它的设计目标是“一次编写,到处运行(Write Once, Run Anywhere)”,这意味着开发者可以使用Java编写应用程序,并在支持...
Java是一种广泛使用的面向对象的编程语言,由Sun Microsystems公司于1995年5月正式发布。它的设计目标是“一次编写,到处运行(Write Once, Run Anywhere)”,这意味着开发者可以使用Java编写应用程序,并在支持...
Java是一种广泛使用的面向对象的编程语言,由Sun Microsystems公司于1995年5月正式发布。它的设计目标是“一次编写,到处运行(Write Once, Run Anywhere)”,这意味着开发者可以使用Java编写应用程序,并在支持...
JavaSE核心 异常处理、多线程基础、IO系统、网络编程、Java反射机制、JVM性能调优(JVM内存结构剖析、GC分析及调优、JVM内存参数优化)、Java泛型、JDK新特性 熟练掌握JavaSE核心内容,特别是IO和多线程;...
Java是一种广泛使用的面向对象的编程语言,由Sun Microsystems公司于1995年5月正式发布。它的设计目标是“一次编写,到处运行(Write Once, Run Anywhere)”,这意味着开发者可以使用Java编写应用程序,并在支持...