一个对象实例占用了多少字节,消耗了多少内存?这样的问题在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字节占用空间分析的更多相关文章

  1. Java finally语句到底是在return之前还是之后执行(JVM字节码分析及内部体系结构)?

    之前看了一篇关于"Java finally语句到底是在return之前还是之后执行?"这样的博客,看到兴致处,突然博客里的一个测试用例让我产生了疑惑. 测试用例如下: public ...

  2. JVM 字节码执行实例分析

    前言 最近在看<Java 虚拟机规范>和<深入理解JVM虚拟机>,对于字节码的执行有了进一步的了解.字节码就像是汇编语言,是 JVM 的指令集.下面我们先对 JVM 执行引擎做 ...

  3. JVM内存问题分析

    JVM运行时数据区: 1.方法区:类信息(类名,访问修饰符.字段描述.方法 描述等).常量.静态变量.即时编译后的class文件等.在GC时用永久代来实现方法区 2.运行时常量池:是方法区的一部分,存 ...

  4. JVM源码分析之SystemGC完全解读

    JVM源码分析之SystemGC完全解读 概述 JVM的GC一般情况下是JVM本身根据一定的条件触发的,不过我们还是可以做一些人为的触发,比如通过jvmti做强制GC,通过System.gc触发,还可 ...

  5. JVM 字节码(三)异常在字节码中的处理(catch 和 throws)

    JVM 字节码(三)异常在字节码中的处理(catch 和 throws) 在 ClassFile 中到底是如何处理异常的呢? 一.代码块异常 catch catch 中的异常代码块在异常是如何处理的呢 ...

  6. JVM 字节码(二)方法表详解

    JVM 字节码(二)方法表和属性表 上一节中对 ClassFile 的整体进行了五个详细的说明, 本节围绕 ClassFile 最重要的一个内容 - 方法表的 Code 属性展开 ,更多 JVM Me ...

  7. JVM 字节码(一)字节码规范

    JVM 字节码(一)字节码规范 JVM 学习资源 Java ClassFile 字节码规范(Oracle) Java 虚拟机规范(Java SE 7 中文版) (周志明等译) Java 反编译工具 - ...

  8. Java并发编程原理与实战八:产生线程安全性问题原因(javap字节码分析)

    前面我们说到多线程带来的风险,其中一个很重要的就是安全性,因为其重要性因此,放到本章来进行讲解,那么线程安全性问题产生的原因,我们这节将从底层字节码来进行分析. 一.问题引出 先看一段代码 packa ...

  9. Java字节码分析

    目录 Java字节码分析 查看字节码详细内容 javap 实例分析 Java字节码分析 对于源码的效率,但从源码来看有时无法分析出准确的结果,因为不同的编译器版本可能会将相同的源码编译成不同的字节码, ...

随机推荐

  1. sizeof 与 字节对齐

    转:http://baike.baidu.com/view/1356720.htm sizeof是运算符,可用于任何变量名.类型名或常量值,当用于变量名(不是数组名)或常量时,它不需要用圆括号.    ...

  2. 自动清理MySQL binlog日志

    开启MySQL binlog日志的服务器,如果不设置自动清理日志,默认binlog日志一直保留着,时间一长,服务器磁盘空间被binlog日志占满,导致MySQL数据库出错. 使用下面方法可以安全清理b ...

  3. generator详解

    generator函数 yield可以返回值,也可以传入值 形式: 注意!generator不能写成arrow function的形式!!! function *函数(){ 代码1... let a ...

  4. indexOf与includes的比较

    indexOf和includes都代表检测数组或字符串中是否包含某一个元素 其中indexOf返回的是数值类型,而includes返回的是布尔类型 var ary = [,,]; console.lo ...

  5. VUE2.0 饿了吗视频学习笔记(四):颜色、跳转、设置、vue-resource

    https://gitee.com/1981633/vue_study.git 源码下载地址,随笔记动态更新中 1.设置选中项颜色 <template> <div id=" ...

  6. SysTick_CLKSourceConfig 这个函数

    systick的寄存器说明是在<Cortex M3权威指南>里说明了! 其实是有选择的,只是默认是AHB/8.通过设置systick的CTRL寄存器的bit2来设置时钟,设置如下: bit ...

  7. 22. SpringBoot 集成 Mybatis

    1. 引入Mybatis的maven 依赖 <dependency> <groupId>org.mybatis.spring.boot</groupId> < ...

  8. html5 流动布局

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name ...

  9. comfirm和prompt的区别

    comfirm和prompt的区别. <html> <title>测试页面</title> <head> </head> <body& ...

  10. [CQOI2012]组装 (贪心)

    CQOI2012]组装 solution: 蒟蒻表示并不会模拟退火,所以用了差分数组加贪心吗.我们先来看题: 在数轴上的某个位置修建一个组装车间 到组装车间距离的平方的最小值. 1<=n< ...