一个对象实例占用了多少字节,消耗了多少内存?这样的问题在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
例如:
Java代码
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看一下这个计算是否准确
规则三:对于继承时,要按照规则二先计算父类的类属性占用情况,再按照规则二计算子类的类属性占用情况,不能将父类和子类的属性混合在一起按规则二分配。
例如:
Java代码
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个字节的倍数对齐
例如:
Java代码
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
例如:
Java代码
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
分享到:
相关推荐
在了解JVM字节码之前,对于Java程序员而言,掌握Java底层知识,尤其是虚拟机和字节码的工作原理,对于成为一名优秀的开发者是很有帮助的。因此,本文从最简单的Java程序——打印"Hello, World"开始,逐步介绍如何将...
Java虚拟机(JVM)是Java程序运行的基础,它负责解释和执行字节码,提供了一个平台无关的运行环境。JVM性能优化是提升Java应用效率的关键环节,涉及到内存管理、垃圾回收、线程调度等多个方面。以下是对"Java JVM及...
例如,通过使用VisualVM(压缩包中的visualvm_14可能是一个VisualVM的版本),我们可以监控和分析JVM的类加载行为,包括类加载时间、内存占用等,从而帮助我们更好地调试和优化应用。VisualVM提供了丰富的功能,如...
**JVM (Java Virtual Machine)**是Java平台的核心部分,它负责执行字节码。 1. **JVM的工作流程**: - 加载Class文件。 - 解释执行字节码。 - 或者通过JIT编译器将热点代码转换为本地机器码。 2. **HotSpot VM*...
在Java编程语言中,了解一个对象占用的内存字节数对于优化内存使用和理解程序性能至关重要。本篇文章将深入探讨如何计算Java对象占用的内存字节数,以及影响这一数值的因素。 首先,Java对象在堆内存中由四个部分...
Java虚拟机(JVM)是运行Java应用程序的关键组件,它负责管理内存、执行字节码以及处理线程等任务。当JVM遇到问题,如内存溢出或长时间的垃圾回收,它可能会生成堆栈转储(dump)文件,这些文件包含了JVM在特定时刻...
JVM指令集的设计简洁而高效,大部分指令占用一个字节的空间,便于快速解码和执行。 ##### 栈式架构 JVM采用了基于栈的架构,这种方法有利于简化指令集设计,同时也有助于提高执行效率。 ##### 安全性 安全性是...
Java JVM(Java虚拟机)是Java程序运行的基础,它负责解释和执行字节码,使得Java具有跨平台的能力。INSTR在Java世界中通常不直接对应一个特定的概念,但可能是指反编译过程中的一些指令或者工具。反编译是将已编译...
1. JVM字节码:Java源代码经过编译后生成的中间表示形式,它是JVM能够理解和执行的语言。字节码以二进制格式存储,包含了类的方法定义、操作符、常量池等信息。通过字节码,开发者可以跨越平台边界,实现“一次编写...
每个使用Java的开发者都知道Java字节码是在JRE中运行,而JVM则是JRE中的核心组成部分,承担分析和执行Java字节码的工作,而Java程序员通常并不需要深入了解JVM运行情况就可以开发出大型应用和类库。尽管如此,如果你...
本文将深入探讨如何在Java中获取JVM内存大小,包括堆内存的总量、最大值以及剩余空间,并解析给定代码片段中的关键概念。 ### JVM内存模型 在讨论如何获取JVM内存大小之前,首先需要理解JVM的内存布局。JVM内存...
* 运行 Java 程序:使用 Java 虚拟机(JVM)将字节码文件解释执行。 Java 运行的原理 Java 运行的原理是将 Java 源代码编译成字节码,然后由 JVM 解释执行字节码文件。JVM 负责将字节码文件翻译成机器语言,并执行...
JVM是一种抽象的计算机,它执行字节码,提供了运行Java程序所需的环境。理解JVM的工作原理对于优化Java应用程序性能至关重要。 首先,我们要知道Java程序的编译过程。Java源代码(.java文件)通过Java编译器(javac...
垃圾回收是JVM的一项重要特性,其主要目的是自动识别并回收不再使用的对象所占用的内存空间,从而避免内存泄漏。 - **回收策略**:从JVM方法栈和本地方法栈引出来的引用开始,把每一个引出来的引用作为根依次搜索...
1. 类加载:JVM在运行时会将.java源文件编译成.class字节码文件,然后通过类加载器加载到内存中。这个过程分为加载、验证、准备、解析和初始化五个阶段。 2. 动态链接:JVM支持动态链接,这意味着在运行时可以找到...
首先,Java虚拟机(JVM)是Java平台的核心组成部分,它负责执行Java字节码。C++创建JVM的过程主要分为以下几步: 1. **加载JVM库**:C++程序需要链接到JVM库才能与之交互。这通常通过JNI的`FindLibrary`函数完成,...
在Java应用中,JVM扮演着至关重要的角色,它负责解析字节码、管理内存以及执行线程等。本文将深入探讨JVM内存结构,以及如何进行有效的内存调优。 首先,我们需要了解JVM内存模型。Java内存主要分为五个区域:堆...
在 Java 中,JVM(Java Virtual Machine)扮演着至关重要的角色,它是 Java 语言的 runtime 环境,负责将 Java 字节码翻译成机器代码并执行。下面是对 JVM 的初步了解。 1. JVM 的理解 JVM 是 Java_virtual_...
Java对象在JVM中的内存占用是一个复杂而重要的主题,它涉及到Java虚拟机的内存区域划分、对象头、实例数据以及对齐填充等多个方面。这里我们将深入探讨这些知识点,以便更好地理解和优化Java应用程序的性能。 首先...
Java虚拟机(JVM)是Java开发中的核心组成部分,它负责执行字节码,管理内存,以及优化程序性能。在Java应用的运行过程中,如果出现性能问题,JVM瓶颈定位就显得至关重要。本文将深入探讨如何理解和解决Java JVM的...