在Sun JVM中,(除了数组之外的)对象都有两个机器字(words)的头部。第一个字中包含这个对象的标示哈希码以及其他一些类似锁状态和等标识信息,第二个字中包含一个指向对象的类的引用。另外,任何对象都是8个字节为粒度进行对齐的。这就是对象内存布局的第一个规则:
规则1:任何对象都是8个字节为粒度进行对齐的。
比如,如果调用new Object(),由于Object类并没有其他没有其他可存储的成员,那么仅仅使用堆中的8个字节来保存两个字的头部即可。
继承了Object的类的内存布局
除了上面所说的8个字节的头部,类属性紧随其后。属性通常根据其大小来排列。例如,整型(int)以4个字节为单位对齐,长整型(long)以8个字节为单位对齐。这里是出于性能考虑而这么设计的:通常情况下,如果数据以4字节为单位对齐,那么从内存中读4字节的数据并写入到处理器的4字节寄存器是性价比更高的。
为了节省内存,Sun VM并没有按照属性声明时的顺序来进行内存布局。实际上,属性在内存中按照下面的顺序来组织:
1. 双精度型(doubles)和长整型(longs)
2. 整型(ints)和浮点型(floats)
3. 短整型(shorts)和字符型(chars)
4. 布尔型(booleans)和字节型(bytes)
5. 引用类型(references)
内存使用率会通过这个机制得到优化。例如,如下声明一个类:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
class MyClass {
byte a;
int c;
boolean d;
long e;
Object f;
} |
如果JVM并没有打乱属性的声明顺序,其对象内存布局将会是下面这个样子:
1
2
3
4
5
6
7
8
9
|
[HEADER: 8 bytes] 8
[a: 1 byte ] 9
[padding: 3 bytes] 12
[c: 4 bytes] 16
[d: 1 byte ] 17
[padding: 7 bytes] 24
[e: 8 bytes] 32
[f: 4 bytes] 36
[padding: 4 bytes] 40
|
此时,用于占位的14个字节是浪费的,这个对象一共使用了40个字节的内存空间。但是,如果用上面的规则对这些对象重新排序,其内存结果会变成下面这个样子:
1
2
3
4
5
6
7
8
|
[HEADER: 8 bytes] 8
[e: 8 bytes] 16
[c: 4 bytes] 20
[a: 1 byte ] 21
[d: 1 byte ] 22
[padding: 2 bytes] 24
[f: 4 bytes] 28
[padding: 4 bytes] 32
|
这次,用于占位的只有6个字节,这个对象使用了32个字节的内存空间。
因此,对象内存布局的第二个规则是:
规则2:类属性按照如下优先级进行排列:长整型和双精度类型;整型和浮点型;字符和短整型;字节类型和布尔类型,最后是引用类型。这些属性都按照各自的单位对齐。
现在我们知道如何计算一个继承了Object的类的实例的内存大小了。下面这个例子用来做下练习: java.lang.Boolean。这是其内存布局:
1
2
3
|
[HEADER: 8 bytes] 8
[value: 1 byte ] 9
[padding: 7 bytes] 16
|
Boolean类的实例占用16个字节的内存!惊讶吧?(别忘了最后用来占位的7个字节)。
继承其他类的子类的内存布局
JVM所遵守的下面3个规则用来组织有父类的类的成员。对象内存布局的规则3如下:
规则3:不同类继承关系中的成员不能混合排列。首先按照规则2处理父类中的成员,接着才是子类的成员。
举例如下:
1
2
3
4
5
6
7
8
9
|
class A {
long a;
int b;
int c;
} class B extends A {
long d;
} |
类B的实例在内存中的存储如下:
1
2
3
4
5
|
[HEADER: 8 bytes] 8
[a: 8 bytes] 16
[b: 4 bytes] 20
[c: 4 bytes] 24
[d: 8 bytes] 32
|
如果父类中的成员的大小无法满足4个字节这个基本单位,那么下一条规则就会起作用:
规则4:当父类中最后一个成员和子类第一个成员的间隔如果不够4个字节的话,就必须扩展到4个字节的基本单位。
举例如下:
1
2
3
4
5
6
7
8
9
10
11
12
|
class A {
byte a;
} class B {
byte b;
} [HEADER: 8 bytes] 8
[a: 1 byte ] 9
[padding: 3 bytes] 12
[b: 1 byte ] 13
[padding: 3 bytes] 16
|
注意到成员a被扩充了3个字节以保证和成员b之间的间隔是4个字节。这个空间不能被类B使用,因此被浪费了。
最后一条规则在下面情况下用来节省一些空间:如果子类成员是长整型或双精度类型,并且父类并没有用完8个字节。
规则5:如果子类第一个成员是一个双精度或者长整型,并且父类并没有用完8个字节,JVM会破坏规则2,按照整形(int),短整型(short),字节型(byte),引用类型(reference)的顺序,向未填满的空间填充。
举例如下:
1
2
3
4
5
6
7
8
9
|
class A {
byte a;
} class B {
long b;
short c;
byte d;
} |
其内存布局如下:
1
2
3
4
5
6
7
|
[HEADER: 8 bytes] 8
[a: 1 byte ] 9
[padding: 3 bytes] 12
[c: 2 bytes] 14
[d: 1 byte ] 15
[padding: 1 byte ] 16
[b: 8 bytes] 24
|
在第12字节处,类A“结束”的地方,JVM没有遵守规则2,而是在长整型之前插入一个短整型和一个字节型成员,这样可以避免浪费3个字节。
数组的内存布局
数组有一个额外的头部成员,用来存放“长度”变量。数组元素以及数组本身,跟其他常规对象同样,都需要遵守8个字节的边界规则。
下面是一个有3个元素的字节数组的内存布局:
1
2
3
4
5
|
[HEADER: 12 bytes] 12
[[ 0 ]: 1 byte ] 13
[[ 1 ]: 1 byte ] 14
[[ 2 ]: 1 byte ] 15
[padding: 1 byte ] 16
|
下面是一个有3个元素的长整型数字的内存布局:
1
2
3
4
5
|
[HEADER: 12 bytes] 12
[padding: 4 bytes] 16
[[ 0 ]: 8 bytes] 24
[[ 1 ]: 8 bytes] 32
[[ 2 ]: 8 bytes] 40
|
内部类的内存布局
非静态内部类(Non-static inner classes)有一个额外的“隐藏”成员,这个成员是一个指向外部类的引用变量。这个成员是一个普通引用,因此遵守引用内存布局的规则。内部类因此有4个字节的额外开销。
相关推荐
本文主要为计算机类专业课“软件工程”结课大作业参考资料,主要围绕餐厅的自助点餐系统进行一系列的研究,采用面向对象模型进行开发,完整资源包括需求分析、面向对象设计书、可行性分析、测试文档和使用java初步...
对象模型:描述对象、类及其相互之间关系的静态数据结构;用对象图加以描述。 动态模型:描述系统内对象的相互作用;通常采用状态图加以表示。 功能模型:描述系统内数据数据的变化工程,通常可采用数据流图形式加以...
面向对象设计java信息系统部署,软件的MVC模型 JDBC访问数据流程 (1)加载驱动程序 (2)连接数据库 (3)创建SQL执行器 (4)执行SQL语句 (5)处理查询结果 (6)断开与数据库的连接
基于Java的敬老院运营管理系统 摘要 本敬老院运营管理系统是使用JSP编程语言和Sqlserver数据库共同来完成的,采用面 向对象方法,对敬老院运营管理工作进行设计与实现。分析设计了敬老院运营管理系统 的静态模型和...
JAVA毕业设计影院管理系统的... 四、 论文撰写 本系统采用面向对象方法对系统进行分析与设计,并使用规范的UML图、表和专业术语来描述系统分析、设计、实现、测试过程与模型。并按照软件工程专业论文模版来撰写论文。
10.1 建立精粒度对象模型 10.2 建立粗粒度关系数据模型 10.3 映射组成关系 10.3.1 区分值(Value)类型和实体(Entity)类型 10.3.2 在应用程序中访问具有组成关系的持久化类 10.4 映射复合组成关系 ...
接着介绍了开发本系统所用到部分技术的相关概念和术语,着重分析了面向对象技术和java语言的特点,以及表明了所用技术在本系统中的作用和意义。之后详细地描述了整个系统的功能,然后通过对某医药公司的内部组织结构...
先修课程:面向对象程序设计语言(C++或JAVA)、 数据结构、数据库系统、软件工程 本课程的教学目的 开设该课程是为了培养学生运用面向对象的 思维方式建立软件系统的分析、设计模型,提高 学生软件开发的能力及...
Java生成密钥、保存密钥的实例源码,通过本源码可以了解到Java如何产生单钥加密的密钥(myKey)、产生双钥的密钥对(keyPair)、如何保存公钥的字节数组、保存私钥到文件privateKey.dat、如何用Java对象序列化保存私钥...
问模型更加适合长时间运行的有着大量堆对象需求的应用程序。 本文描述了一个基于堆栈框架 , 用于在运行时检测这些 “ 冷 ” 对象 , 以便在堆的指定 区域封装和隔离它们 , 它们可能优先调出到一个后备存储器 , 从而...
java.util 包含 collection 框架、遗留的 collection 类、事件模型、日期和时间设施、国际化和各种实用工具类(字符串标记生成器、随机数生成器和位数组)。 java.util.concurrent 在并发编程中很常用的实用工具类...
基于Java的视频会议系统(软件程序+WORD论文文档) 2.1.1 技术可行性 网络视频会议是顺应市场的需求而设计的。采用JAVA 编程语言,用eclipse开发平台实现。用到多媒体技术(JAVA 多媒体框架JMF),视频和音频用TRP...
本文描述了JAVA和JSP技术的特点以及在互联网上的使用情况,介绍这两种技术的重要编程方法和两者之关的联系,并完成一个基于这种技术的网上书店系统。 【关键字】JAVA, JavaBeans, Servlet, JSP, 网络编程, 电子商务...
其对象模型是能定义对应真实事物的数据结构,使得程序的任务和任务如何实现 二者之间的转换变得基本上透明。 优点三,由于有了 JVM,一个 Java 应用程序与操作系统或硬件完全隔绝,因此计算机 病毒或其他作祟的代码...
Java存储与读取对象.rar Java局域网通信——飞鸽传书源代码.rar JAVA帮助视图组件库 Help GUI 1.1源代码.rar JAVA开发的打字软件源程序.rar Java开发的简单WEB服务器源码.rar Java数据压缩与传输实例 Java数组倒置 ...
Java生成密钥、保存密钥的实例源码,通过本源码可以了解到Java如何产生单钥加密的密钥(myKey)、产生双钥的密钥对(keyPair)、如何保存公钥的字节数组、保存私钥到文件privateKey.dat、如何用Java对象序列化保存私钥...
开题报告-基于Java的酒店客房管理系统的设计与实现 毕业设计开题报告 课 题 名 称:基于Java的酒店客房管理系统的 设计与实现 姓 名: 班 级: 指 导 教 师: 所 在 系 部: "毕业设计的 "1.毕业设计的内容: " ...