jvm字节占用空间分析
一个对象实例占用了多少字节,消耗了多少内存?这样的问题在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 finally语句到底是在return之前还是之后执行(JVM字节码分析及内部体系结构)?
之前看了一篇关于"Java finally语句到底是在return之前还是之后执行?"这样的博客,看到兴致处,突然博客里的一个测试用例让我产生了疑惑. 测试用例如下: public ...
- JVM 字节码执行实例分析
前言 最近在看<Java 虚拟机规范>和<深入理解JVM虚拟机>,对于字节码的执行有了进一步的了解.字节码就像是汇编语言,是 JVM 的指令集.下面我们先对 JVM 执行引擎做 ...
- JVM内存问题分析
JVM运行时数据区: 1.方法区:类信息(类名,访问修饰符.字段描述.方法 描述等).常量.静态变量.即时编译后的class文件等.在GC时用永久代来实现方法区 2.运行时常量池:是方法区的一部分,存 ...
- JVM源码分析之SystemGC完全解读
JVM源码分析之SystemGC完全解读 概述 JVM的GC一般情况下是JVM本身根据一定的条件触发的,不过我们还是可以做一些人为的触发,比如通过jvmti做强制GC,通过System.gc触发,还可 ...
- JVM 字节码(三)异常在字节码中的处理(catch 和 throws)
JVM 字节码(三)异常在字节码中的处理(catch 和 throws) 在 ClassFile 中到底是如何处理异常的呢? 一.代码块异常 catch catch 中的异常代码块在异常是如何处理的呢 ...
- JVM 字节码(二)方法表详解
JVM 字节码(二)方法表和属性表 上一节中对 ClassFile 的整体进行了五个详细的说明, 本节围绕 ClassFile 最重要的一个内容 - 方法表的 Code 属性展开 ,更多 JVM Me ...
- JVM 字节码(一)字节码规范
JVM 字节码(一)字节码规范 JVM 学习资源 Java ClassFile 字节码规范(Oracle) Java 虚拟机规范(Java SE 7 中文版) (周志明等译) Java 反编译工具 - ...
- Java并发编程原理与实战八:产生线程安全性问题原因(javap字节码分析)
前面我们说到多线程带来的风险,其中一个很重要的就是安全性,因为其重要性因此,放到本章来进行讲解,那么线程安全性问题产生的原因,我们这节将从底层字节码来进行分析. 一.问题引出 先看一段代码 packa ...
- Java字节码分析
目录 Java字节码分析 查看字节码详细内容 javap 实例分析 Java字节码分析 对于源码的效率,但从源码来看有时无法分析出准确的结果,因为不同的编译器版本可能会将相同的源码编译成不同的字节码, ...
随机推荐
- 中南大学2018年ACM暑期集训前期训练题集(入门题) Q: Simple Line Editor
数据有毒,一个一个读字符是错,整个字符串读入,一次就A了. 总之,数据总是没有错的,还是对c++了解地不够深刻,还有,在比赛中,一定要有勇气重构代码 错误代码: #include<iostrea ...
- 基于tcp和多线程的多人聊天室-C语言
之前在学习关于网络tcp和多线程的编程,学了知识以后不用一下总绝对心虚,于是就编写了一个基于tcp和多线程的多人聊天室. 具体的实现过程: 服务器端:绑定socket对象->设置监听数-> ...
- Ansible拷贝文件遇到的问题
ansible报错Aborting, target uses selinux but python bindings (libselinux-python) aren't installed 报错内容 ...
- python-web开发环境搭建
一.安装distribute或setuptools,我用的distribute 下载链接:https://pypi.python.org/pypi/distribute [root@yeebian o ...
- jackson的自动检测机制
jackson允许使用任意的构造方法或工厂方法来构造实例 使用@JsonAutoDetect(作用在类上)来开启/禁止自动检测 fieldVisibility:字段的可见级别 ANY:任何级别的字段都 ...
- 通过lua栈了解lua与c的交互
lua是如何执行的 其中分析.执行部分都是c语言实现的. lua与c的关系 lua的虚拟机是用c语言实现的,换句话说一段lua指令最终在执行时都是当作c语言来执行的,lua的global表,函数调用栈 ...
- Spring session(redis存储方式)监听导致创建大量redisMessageListenerContailner-X线程
待解决的问题 Spring session(redis存储方式)监听导致创建大量redisMessageListenerContailner-X线程 解决办法 为spring session添加spr ...
- java中生成验证码,以及验证码的使用
java中生成验证码,以及验证码的使用: 1:验证码生成工具类: import java.awt.Color; import java.awt.Font; import java.awt.Graphi ...
- Entry point (0x08000000) points to a Thumb instruction but is not a valid Thumb code pointer.
1.菜单 project-options-linker-misc controls加入 --entry Reset_Handler --first __Vectors 2.导入startup_stm3 ...
- urllib和urllib2之间的区别
urllib和urllib2都是接受URL请求的相关模块,但是提供了不同功能. urllib2可以接受一个Request类的实例来设置URL请求的headers,urllib仅可以接受URL.这意味着 ...