java 对象 内存_java对象在内存的大小

前言

一直以来,对java对象大小的概念停留在基础数据类型,比如byte占1字节,int占4字节,long占8字节等,但是一个对象包含的内存空间肯定不只有这些。

假设有类A和B,当new A()或者new B()后,实际占用的java内存是多大呢?下面就对此进行详细分析。

static class A{

String s = new String();

int i = 0;

}

static class B{

String s;

int i;

}

对象大小分析

如图1,java对象在内存中占用的空间分为3类, 1. 对象头(Header); 2. 实例数据(Instance Data); 3. 对齐填充(Padding)。而我们常说的基础数据类型大小主要是指第二类实例数据。

419bb82dff861628e04c64ac449ab0a2.png

图1

对象头

HotSpot虚拟机的对象头包括两部分信息:

markword和klass 。第一部分markword,用于存储对象自身的运行时数据,如哈希码(HashCode)、GC分代年龄、锁状态标志、线程持有的锁、偏向线程ID、偏向时间戳等。 另外一部分是klass类型指针,即对象指向它的类元数据的指针,虚拟机通过这个指针来确定这个对象是哪个类的实例。

数组长度

如果对象是一个数组, 那在对象头中还必须有一块数据用于记录数组长度,也就是一个int类型的对象,占4字节。

对象头占用空间

1. 在32位系统下,存放Class指针的空间大小是4字节,MarkWord是4字节,对象头为8字节。

2. 在64位系统下,存放Class指针的空间大小是8字节,MarkWord是8字节,对象头为16字节。

3. 在64位开启指针压缩的情况下 -XX:+UseCompressedOops,存放Class指针的空间大小是4字节,MarkWord是8字节,对象头为12字节。

4. 如果对象是数组,那么额外增加4个字节

实例数据

实例数据部分是对象真正存储的有效信息,也是在程序代码中所定义的各种类型的字段内容。无论是从父类继承下来的,还是在子类中定义的,都需要记录起来。

对齐填充

最后一块对齐填充空间并不是必然存在的,也没有特别的含义,它仅仅起着占位符的作用。这是由于HotSpot VM的自动内存管理系统要求对象起始地址必须是8字节的整数倍,换句话说,就是对象的大小必须是8字节的整数倍。

如何查看java对象大小

1. 基于JDK1.8

JDK1.8有一个类`jdk.nashorn.internal.ir.debug.ObjectSizeCalculator`可以评估出对象的大小

// 直接调用静态方法即可使用

ObjectSizeCalculator.getObjectSize(obj)

2. spark库

spark库中有一个类`org.apache.spark.util.SizeEstimator`

// 直接调用静态方法即可使用

SizeEstimator.estimate(obj)

3. 基于JDK1.5的Instrumentation

// 需要编译成jar调用,没有前者方便

案例

分析完对象的组成结构后,再回头来看那个问题

// 对象A: 对象头12B + 内部对象s引用 4B + 内部对象i 基础类型int 4B + 对齐 4B = 24B

// 内部对象s 对象头12B + 2个内部的int类型8B + 内部的char[]引用 4B + 对齐0B = 24B

// 内部对象str的内部对象char数组 对象头12B + 数组长度4B + 对齐0B = 16B

// 总: 对象A 24+ 内部对象s 24B + 内部对象s的内部对象char数组 16B =64B

class A {

String s = new String();

int i = 0;

}

// 对象B:对象头12B + 内部对象s引用 4B + 内部对象i 基础类型int 4B + 对齐 4B = 24B

// s没有被分配堆内存空间

// 总: 对象B 24B

class B {

String s;

int i = 0;

}

总结

对象在jvm中不是完全连续的,这是由于GC的原因,总会出现散乱的内存。这就导致了jvm必须为每个对象分配一段内存空间来存储其引用的指针,再结合对象的其他必须的元数据,使得对象在持有真实数据的基础上还需要维护额外的数据。

在写java代码需要小心这些jvm内存陷阱。

参考

// stackoverflow给出的几种计算对象大小方法

Java对象的内存模型(一)

前言 新人一枚,刚刚入门编程不久,各方面都在学习当中,博文有什么错误的地方,希望我们可以多多交流! 最近,在开发App后台过程中,需要将项目部署到云服务器上.而云服务器的内存大小却只有1G.要如何做到 ...

JVM总结-java对象的内存布局

在 Java 程序中,我们拥有多种新建对象的方式.除了最为常见的 new 语句之外,我们还可以通过反射机制.Object.clone 方法.反序列化以及 Unsafe.allocateInstance ...

Java对象的内存(一)

前言 新人一枚,刚刚入门编程不久,各方面都在学习当中,博文有什么错误的地方,希望我们可以多多交流! 最近,在开发App后台过程中,需要将项目部署到云服务器上.而云服务器的内存大小却只有1G.要如何做到 ...

Java对象的内存布局以及对象的访问定位

一 Java对象的内存布局 在HotSpot虚拟机中,对象在内存中的布局分为3个区域 对象头(Header) Mark Word(在32bit和64bit虚拟机上长度分别为32bit和64bit)存储 ...

3 Java对象的内存布局以及对象的访问定位

先来看看Java对象在内存中的布局   一 Java对象的内存布局 在HotSpot虚拟机中,对象在内存中的布局分为3个区域 对象头(Header) Mark Word(在32bit和64bit虚拟机 ...

灵魂拷问:Java对象的内存分配过程是如何保证线程安全的?(阿里面试)

JVM内存结构,是很重要的知识,相信每一个静心准备过面试的程序员都可以清楚的把堆.栈.方法区等介绍的比较清楚. 上图,是一张在作者根据中描述的J ...

JAVA | Java对象的内存分配过程是如何保证线程安全的?

JAVA | Java对象的内存分配过程是如何保证线程安全的? 专注于Java领域优质技术,欢迎关注 作者 l Hollis 来源 l Hollis(ID:hollischuang) JVM内存结构, ...

Java对象的内存布局

对象的内存布局 平时用java编写程序,你了解java对象的内存布局么? 在HotSpot虚拟机中,对象在内存中存储的布局可以分为3块区域: 对象头 实例数据 对齐填充 对象头 对象头包括两部分信息: ...

java对象在内存中的分配

java对象在内存中的分配 http://blog.csdn.net/qq_30753945/article/details/54974899

随机推荐

Scala正则和抽取器:解析方法参数

在中概括了正则表达式的基础知识, 本文讲解如何使用正则表达式解析方法参数,从而可以根据 DAO 自动生成 Service. 在做 Java 项目时,常常要根据 DAO ...

优秀c++开源项目集合

本文会持续更新, 我希望通过这篇文章把我看到过的优秀开源项目记录下来, 有时间仔细阅读. cockroachdb 前googler开发的开源的spanner数据库: https://github.co ...

ReactNative学习之Html基本标签使用

前言: 前面简单学习了html简单标签的使用,今天学习一下其他的标签的使用. HTML的超链接 1.)创建一个超链接

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值