一个对象实例占用了多少字节,消耗了多少内存?这样的问题在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. java基础基础总结----- 常用了解java(二)

    一.Java的发展历史 1998年,Java 2 Platform J2SE.J2ME.J2EE 2005年,Java10周年,重新命名: J2SE → Java SE → Standard Edit ...

  2. 目前最全的IT技术问答、社区、科技服务网站合集

    资源网站 推荐一个资源丰富齐全的网站:风云社区(SCOEE),主要特点是提供的是纯净.优质.无广告.无附加东西的资源.资源很丰富,包括各类软件资源(mac.Windows.ios.ipad.安装等软件 ...

  3. Mysql忘记数据库密码以及用户授权案例展示

    Mysql忘记数据库密码以及用户授权案例展示 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 大家在学习MySQL时如果很长一段时间不使用密码是不是就忘记MySQL的管理密码啦?这种 ...

  4. 【1】【JUC】JDK1.8源码分析之ArrayBlockingQueue,LinkedBlockingQueue

    概要: ArrayBlockingQueue的内部是通过一个可重入锁ReentrantLock和两个Condition条件对象来实现阻塞 注意这两个Condition即ReentrantLock的Co ...

  5. java AOP使用注解@annotation方式实践

       java AOP使用配置项来进行注入实践 AOP实际开发工作比较常用,在此使用注解方式加深对面向切面编程的理解 废话不多少,先看下面的实例代码 场景: 1.未满一岁的小孩,在执行方法之前打印:“ ...

  6. C#在Win10与非Win10 Windows系统鼠标滚动编程的一点区别。

    C#在win10和非Win10上处理鼠标滚动有一些区别,建一个Form1,放置一个FlowLayoutPanel ,类型的Panel1 Panel.MouseWheel += PanelOnMouse ...

  7. static, const

    static 静态的,类的静态成员函数,静态成员变量是和类相关的,但不和具体对象相关.即使没有具体对象,也能调用类的静态成员函数和成员变量.一般类的静态函数就是一个全局函数,只是作用域在包含它的文件中 ...

  8. pyqt5-多线程QThread类

    要实现多线程,我们要先继承QThread类并重新实现其中的run()函数,也就是说把耗时的操作放入run()函数中 import sys from PyQt5.QtCore import Qt, QT ...

  9. Python杀死windows进程

    import os import pandas as pd """ TCP 192.168.1.155:63758 129.211.126.69:4730 ESTABLI ...

  10. mysql select 时间戳转标准时间写法

    select  FROM_UNIXTIME(create_time, '%Y-%m-%d %H:%i:%S') as create_time from tabName