一个对象实例占用了多少字节,消耗了多少内存?这样的问题在c或c++里使用sizeof()方法就可以得到明确答案,在java里好像没有这样的方法(java一样可以实现),不过通过jmap工具倒是可以查看出一个对象的占用内存的大小,这里介绍一种通过分析java代码计算内存使用情况的方法。
注意,一下讨论的情况都是基于32位机,不适用用64位机,JVM是sun的HotSpot,不同的虚拟机实现可能会不同
规则一:每个对象被按照8bytes粒度对齐(数组除外)
在jvm中每个对象(数组除外)都有一个头,这个头有两个字,第一个字存储的时对象的一些标志位信息,例如:锁标志位、经历了几次gc等信息,第二个字是一个引用,指向了这个类的类信息。这里jvm给这两个字留了8个字节的空间(这个为啥用8个字节空间不是很清楚,一个字即两个字节,我一直认为4个字节就够了)
按规则一:new Object();这个Object实例就占用了8个字节
规则二:为类属性分配存储空间时不是按照类中定义的属性顺序,而是按如下的顺序:
1、double\long;----8bytes
2、int\float;----4bytes
3、char\short;----2bytes
4、boolean\byte;----1bytes
5、reference;----4bytes
例如:
public class A {
byte a;
char b;
int c;
long d;
Object e;
}
属性 |
需要字节数 |
累积字节数 |
header |
8bytes |
8 |
long:d |
8bytes |
16 |
int:c |
4bytes |
20 |
char:b |
2bytes |
22 |
byte:a |
1bytes |
23 |
Object:e |
4bytes |
27 |
|
padding 5bytes |
32
|
最后一行padding 5bytes的目的是,规则一中描述每个对象按照8个字节的粒度对齐,这样下一个分配的对象的开始位置必须在8的倍数上,而离27最近的8的倍数是32,因此加了5bytes。A占用32bytes
可以用jmap看一下这个计算是否准确
规则三:对于继承时,要按照规则二先计算父类的类属性占用情况,再按照规则二计算子类的类属性占用情况,不能将父类和子类的属性混合在一起按规则二分配。
例如:
class B{
long a;
int b;
int c;
}
class BB extends B{
long d;
}
属性 |
占用字节数 |
累计字节数 |
header |
8 |
8 |
a |
8 |
16 |
b |
4 |
20 |
c |
4 |
24 |
d |
8 |
32 |
这里累计字节正好是8的倍数,满足规则一,因此不用padding字节。BB对象内存占用了32bytes
规则四:父类的最后一个属性和子类第一个属性必须按4个字节的倍数对齐
例如:
class B{
long a;
int b;
char c;
}
class BB extends B{
long d;
}
属性 |
占用的字节 |
累计字节 |
head |
8 |
8 |
a |
8 |
16 |
c |
2 |
18 |
|
padding 2 |
20 |
d |
8 |
28 |
|
padding 4 |
32 |
第一次padding2是因为属性c分配内存后,不满足父类最后一个属性和子类第一个属性按4字节粒度对齐(18除4除不开),因此需要添加两个字节使其可以按4字节粒度对齐。
第二次paadding4是依据规则一
规则五:当子类的第一个属性是double或long,但是父类不能按8字节粒度对齐时,子类内存分配时的顺序将不按规则二进行,而是按:先int\float、char\short、boolean\byte、reference、long\double
例如:
class A{
byte a;
}
class B extends A{
long b;
short c;
byte d;
}
属性 |
占用字节数 |
累计占用字节数 |
head |
8 |
8 |
a |
1 |
9 |
|
padding 3 |
12 |
c |
2 |
14 |
d |
1 |
15 |
|
padding 1 |
16 |
b |
8 |
24 |
第一次 padding 3是根据规则四
第二次 padding 1是因为b属性是8个字节,因此需要按8个字节粒度对齐。B占用24bytes
对于数组,与普通对象不同的是在头部,头部多了4个字节用于存储长度信息。因此数组的head是12bytes而不是8bytes
具体内容可以查看原文:http://www.codeinstructions.com/2008/12/java-objects-memory-structure.html
分享到:
相关推荐
总结来说,理解并测量Java对象内存大小对于优化内存使用、提高程序性能以及构建高效缓存系统具有重要意义。开发者需要了解JVM内存分配机制,掌握测量对象大小的方法,并根据结果调整对象结构和缓存策略,以达到最优...
在Java世界中,JVM(Java虚拟机)是运行Java应用程序的关键组件。它负责解析字节码、管理内存以及执行程序。...通过运行这些脚本,我们可以获取更具体的对象内存占用信息,进一步优化我们的Java应用。
这个“Java内存使用系列一Java对象的内存占用”主题旨在深入探讨Java对象在内存中的表现,以及如何有效地管理这些资源。Java开发人员需要理解内存分配、垃圾回收机制以及如何避免内存泄漏,以确保程序的高效运行。 ...
当缓存大小成为问题时,可以通过调整缓存策略(如使用弱引用、软引用或计算对象的引用强度)来减少内存占用。同时,及时释放不再使用的对象,防止内存泄漏,也是提升系统稳定性和效率的重要手段。 总的来说,理解...
本文将详细探讨Java对象在JVM中的创建过程以及其内存布局,帮助读者更深入地理解Java对象是如何在内存中产生的。 #### 二、对象的创建 Java对象是由类实例化的结果,当我们使用`new`关键字创建一个对象时,实际上...
本示例主要探讨如何测试Java对象占用的内存大小,以便更好地理解内存使用情况。 首先,`SizeOf.java`可能是一个实现自定义内存大小计算的类。在Java中,由于垃圾回收机制的存在,直接获取对象的内存占用并不像C++等...
首先,我们需要理解Java对象内存占用的基本原理。每个Java对象都由三部分组成:对象头(Object Header)、实例数据(Instance Data)和对齐填充(Padding)。对象头包含对象引用和类型信息,实例数据是对象实际存储...
Java内存分析是一个关键的优化步骤,特别是在开发大型的、高性能的应用程序时。MAT(Memory Analyzer Tool)是由IBM开发的一款强大的Java堆内存分析器,它的全名是Eclipse Memory Analyzer。这款工具是开源的,完全...
- jProfiler7提供了详细的内存分配和存活周期视图,帮助开发者定位内存占用大的对象和可能导致问题的代码片段。 2. **jProfiler7的核心功能** - **对象分配追踪**:实时监控对象创建过程,找出哪个类或方法导致了...
MAT可以通过heap dump文件对JVM的内存状态进行深度分析,提供详细的内存占用报告,包括对象统计、支配树分析、引用路径查找等功能。通过这些功能,开发者可以定位到内存消耗过多的类或者对象,找出可能导致内存泄漏...
### Java的内存管理机制分析 #### 一、Java内存区域划分 Java的内存管理机制将内存分为以下几个区域: 1. **栈(Stack)**: - 存储局部变量(如基本类型的变量和对象的引用)。 - 每个线程拥有一个独立的栈。 ...
"java-sizeof-0.0.4"是一个用于分析Java对象内存占用的工具,它可以帮助开发者更好地理解对象在运行时的内存消耗。这个工具提供了查看对象实例大小的能力,这对于调试和性能优化非常有用。"java-sizeof-0.0.4"包含三...
本篇文章将深入探讨如何计算Java对象占用的内存字节数,以及影响这一数值的因素。 首先,Java对象在堆内存中由四个部分组成:对象头(A)、基本类型域(B)、引用类型域(C)和填充物(D)。 **对象头(A)**: ...
堆内存是Java对象的主要存储区域,而栈内存主要存储方法的局部变量。通过理解这些区域的用途,我们可以更好地分析内存使用。 垃圾收集(Garbage Collection, GC)是Java内存管理的核心。Java自动进行垃圾回收,释放...
Java中的多态性是面向对象编程的一个核心特性,它允许我们使用父类引用指向子类对象,从而实现灵活的代码设计。多态性分为编译时多态和运行时多态,其中运行时多态是Java中最常见的形式,也称为动态绑定。在深入探讨...
GC会定期检测不再使用的对象并释放其占用的内存。理解垃圾回收机制有助于优化内存使用,避免内存泄漏。 3. **内存碎片**:长时间运行的Java应用可能导致堆内存碎片。碎片化会影响内存效率,因为可用的连续内存块...
1. **捕获快照**:使用内存分析工具在程序运行的不同阶段捕获内存快照,对比分析,找出内存占用增加的原因。 2. **识别泄漏对象**:通过分析快照,找到长时间存活且占用内存大的对象,这些可能是潜在的内存泄漏源。...
MAT提供了一种可视化的界面,通过分析heap dump文件,能够帮助我们深入理解Java应用程序的内存使用情况,找出内存泄漏的源头。 使用MAT,你可以进行以下操作: 1. **内存概述**:查看总体内存分配情况,包括最大的...
接着,文档详细分析了Java对象的内存占用情况。每个对象都会在内存中占用一定的空间,用来存储对象的类型指针、哈希码、GC分代年龄、同步锁信息等。尽管这些信息占用的大小在不同的JVM实现中可能有所差异,但一般...
Java内存管理是一个关键的议题,...总的来说,理解Java内存管理和垃圾收集机制,以及如何使用工具进行分析和定位,是优化Java应用程序性能、避免内存泄漏的关键。通过有效的内存管理,可以确保程序高效且稳定地运行。