jvm之对象大小分析

这篇具有很好参考价值的文章主要介绍了jvm之对象大小分析。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

写在前面

本文看下计算对象大小相关内容。

1:基础内容

1.1:对象的结构

一个对象由对象头和对象体组成,其中对象头包含如下内容:

标记字(mark word):存放GC年龄信息,对象锁信息等,占用8个字节
class指针:指向方法区中的class文件信息,占用4个字节(指针压缩)
数组长度信息(array length):数组特有,记录数组的长度,int表示,所以是8个字节,该项非数组可忽略

对象体存储的是具体的对象内容以及内部padding:

对象内容:具体的属性信息
内部padding:如果不是8字节的整数倍,则填充为8字节的整数倍,因为CPU是以8byte为单位来获取数据的

当对象头和对象体的总大小不是8byte的整数倍时需要通过外部aligment来填充到整数倍,整体结构如下:

jvm之对象大小分析

因此就算是一个空对象其大小也至少是标记字8字节+class指针4字节+对象内容0字节+外部alignment4字节=16字节。如下定义一个类:

public class EmptyObject {
}

然后创建100个对象实例,如下:

public class Main {

    public static void main(String[] args) throws InterruptedException {
        List<EmptyObject> oneHundredList = new ArrayList<>();
        for (int i = 0; i < 100; i++) {
            oneHundredList.add(new EmptyObject());
        }
        Thread.sleep(Integer.MAX_VALUE);
    }
}

如下查看:

C:\Users\Administrator>jps -l
7984 org.jetbrains.jps.cmdline.Launcher
12692
20196 sun.tools.jps.Jps
3512 dongshi.daddy.objectsize.Main
14892
19580 org.jetbrains.idea.maven.server.RemoteMavenServer36
C:\Users\Administrator>jmap -histo 3512 > d:\\test\\emptyobj100.txt

jvm之对象大小分析

可以看到每个是16字节,当我们定义一个int属性,大小是多少呢?依然是16字节,因为有了4字节的int就不要4字节的外部alignment了,如下:

public class EmptyObject {
    int num;
}

重复执行创建100个对象实例的程序:

C:\Users\Administrator>jps -l
11780 sun.tools.jps.Jps
12692
12568 dongshi.daddy.objectsize.Main
14892
19356 org.jetbrains.jps.cmdline.Launcher
19580 org.jetbrains.idea.maven.server.RemoteMavenServer36

C:\Users\Administrator>jmap -histo 12568 > d:\\test\\withint.txt

jvm之对象大小分析

那如果我们再添加一个short成员变量,此时一个EmptyObject占用多大内存呢?答案是24字节,计算如下:

对象头标记字:8字节
对象头class指针:4字节

对象内容int:4字节
对象内容short:2字节
内部padding:2字节

此时总共20字节,不是8整倍数,所以需要外部alignment4字节

所以总共是24字节

修改如下:

public class EmptyObject {
    int num;
    short shortNum;
}

重新生成100个对象实例后查看:

C:\Users\Administrator>jmap -histo 3952 | findstr ":EmptyObject"

C:\Users\Administrator>jmap -histo 3952 | findstr "EmptyObject"
  28:           100           2400  dongshi.daddy.objectsize.EmptyObject

可以看到确实是24字节。

2:包装类型和原生类型

先说结论,包装数据类型要比原生类型占用更多的内存,因为多了对象头和填充的内存占用,分别来看下Integer和Long。

2.1:Integer

对于int,其占用4个字节,但是如果是其包装类型Integer,则要占用(对象头标记字8字节+对象头class指针4字节+对象内容int本身4字节=16字节),如下也可以验证:

C:\Users\Administrator>jmap -histo 3952 | findstr "java.lang.Integer"
  19:           258           4128  java.lang.Integer

总大小4128除以对象个数258等于16字节。

2.2:Long

对于long,其占用8个字节,但是如果是其包装类型Long,则要占用(对象头标记字8字节+对象头class指针4字节+对象内容int本身8字节+外部alignment4字节=24字节),如下也可以验证:

C:\Users\Administrator>jmap -histo 7212 | findstr "java.lang.Long"
  28:           100           2400  java.lang.Long

可以看到每个的大小是2400/100=24字节

所以在实际编码中,能使用基本数据类型的还是使用基本数据类型,因为包装数据类型的内存占用量相比于基础数据类型要多出几倍。

3:数组

以int数组为例,对于一维的int数组,其结构如下:

jvm之对象大小分析

因此如果是int[256]则大小是(标记字8字节+class指针4字节+数组长度4字节+内容256*4=1040字节)

对于二维数组int[dim1][dim2]而言,每个int[dim2]都是使用一个额外的对象来表示的,因此会占用更大的内存空间,如果我们将int[256]使用int[128][2]来表示的话,则结构如下图:

jvm之对象大小分析

每个元素的大小是(指针4字节+int[2]对象24字节=28字节),共128个,所以大小是128*28=3584字节,再加上第一纬的标记头8字节,class指针4字节,数组长度4字节,共3600字节,可看到存储相同量的元素,int[128][2]比int[256]多占用了(3600-1040=2560字节)的内存空间。

所以,在实际工作中,尽量避免使用多维数组,有需要也尽量使用一维数组来实现,将一维数组折叠一下就行了。

4:String

想要分析处String占用的内存大小,需要先来看下String的定义(只列出会占用堆内存的)

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {
    /** The value is used for character storage. */
    private final char value[];

    /** Cache the hash code for the string */
    private int hash; // Default to 0
}

结构如下:

jvm之对象大小分析

则一个空string占用的大小是36字节,如果是不包括String对象头的话,则大小是24字节。

5:普通的类

如下的类:

public class EmptyObject {
    int a;
    byte b;
    Integer c = new Integer(10);
}

内存结构如下:

jvm之对象大小分析

所以总大小是(标记字8字节+class指针4字节+int a 4字节+byte b 1字节+Integer c指针 4字节=21字节),再对齐,因此是24字节,如下验证:

public class Main {

    public static void main(String[] args) throws InterruptedException {
        List<EmptyObject> oneHundredList = new ArrayList<>();
        for (int i = 0; i < 100; i++) {
            oneHundredList.add(new EmptyObject());
        }
        Thread.sleep(Integer.MAX_VALUE);
    }
}
:\Users\Administrator>jps -l
13200 dongshi.daddy.objectsize.Main
12692
6824 sun.tools.jps.Jps
14892
19580 org.jetbrains.idea.maven.server.RemoteMavenServer36
3308 org.jetbrains.jps.cmdline.Launcher

C:\Users\Administrator>jmap -histo 13200 | findstr "EmptyOb"
  28:           100           2400  dongshi.daddy.objectsize.EmptyObject

可以看到每个确实是24字节。

写在后面

参考文章列表

Java中的String到底占用多大的内存空间?带你一步步验证! 。文章来源地址https://www.toymoban.com/news/detail-461950.html

到了这里,关于jvm之对象大小分析的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 本文带你了解透彻云计算(前世,今生,未来)

    作者简介:一名在校云计算网络运维学生、每天分享云计算运维的学习经验、和学习笔记。   座右铭:低头赶路,敬事如仪 个人主页:网络豆的主页​​​​​​ 对于云计算,我们将会通过云计算的前世,今生,未来,特点,原理等几个方面进行讲解。 云计算的一个 核心

    2024年01月21日
    浏览(39)
  • 设置IDEA内置JVM内存大小(堆空间大小设置)

    目录 理论知识: 1、默认堆空间大小是根据物理机内存大小决定的。 2、以上只是“理论值”,“实际值”会比“理论值”小一些。 堆空间大小设置(多图): 验证生效与否: 其他相关文章推荐: 1、默认堆空间大小是根据物理机内存大小决定的。 假设物理机是 16G 内存,那

    2024年02月20日
    浏览(43)
  • 矩阵分析与计算机视觉:从特征提取到对象识别

    计算机视觉是人工智能领域的一个重要分支,它涉及到计算机对图像和视频等多媒体数据进行处理和理解的技术。矩阵分析是线性代数的一个重要分支,它涉及到矩阵的运算、分解、求解等方面。在计算机视觉中,矩阵分析起到了关键的支持作用,因为图像和视频数据都可以

    2024年01月19日
    浏览(41)
  • 【linux】挖矿病毒nanominer伪装成python占用服务器GPU!本文带你分析并杀毒!

    可以看到root用户将GPU的核心跑满了每个占用都是100%,显存吃了6G多。 不能正常显示GPU被哪些进程占用 在/tmp/.x/目录中 总结: amdmemtweak: 优化显存时序,提高挖矿效能 config.ini: 挖矿配置文件 doos.pid: 挖矿进程的pid号 logs: 挖矿病毒的输出log nanominer: 3.7.7-linux版本的挖矿病毒,这

    2024年02月14日
    浏览(41)
  • Jvm对象回收算法-JVM(九)

    上篇文章介绍了jvm运行时候对象进入老年代的场景,以及如何避免频繁fullGC。 Jvm参数设置-JVM(八) 老年代分配担保机制 这个机制的目的是为了提升效率,在minorGC之前,会有三次判断,之后再次minorGC速度会很快。 老年代剩余空间是否 大于 年轻代里现在所有对象 大于的话则

    2024年02月13日
    浏览(52)
  • 【Turfjs的java版本JTS】前面讲了Turfjs可以实现几何计算,空间计算的功能,如果后端要做这项功能也有类似的类库,JTS

    JTS = Java Topology Suite 几何计算: 1. 前端js就用这个 Turfjs的类库。参考网站: 计算两线段相交点 | Turf.js中文网 2. 后端java语言就可以用 JTS这个类库,参考网站:  JTS参考网站: 1. https://github.com/locationtech/jts GitHub - locationtech/jts: The JTS Topology Suite is a Java library for creating and m

    2024年02月09日
    浏览(35)
  • Jvm创建对象之内存分配-JVM(七)

    上篇文章介绍了jvm创建,会校验是否已加载类,没有则加载,通过之前学的源码,classLoader加载完之后,虚拟机开始给类分配内存,指针移动分配和free链表分配,解决并发分配情况用cap和TLAB方法。之后设置对象头部信息,有mark word线程锁,分代年龄等,klass pointer。还有指针

    2024年02月13日
    浏览(68)
  • JVM-JVM中对象的结构

    对象内存布局 对象里的三个区: 对象头(Header):Java对象头占8byte。如果是数组则占12byte。因为JVM里数组size需要使用4byte存储。 标记字段MarkWord: 用于存储对象自身的运行时数据,它是synchronized实现轻量级锁和偏向锁的关键。 默认存储:对象HashCode、GC分代年龄、锁状态等

    2024年02月20日
    浏览(41)
  • KMP算法——通俗易懂讲好KMP算法:实例图解分析+详细代码注解 --》你的所有疑惑在本文都能得到解答

    KMP 是一个 解决模式串在文本串是否出现过 ,如果出现过,最早出现的位置的经典算法。 Knuth-Morris-Pratt 字符串查找算法,简称为 “KMP 算法”,常用于 在一个文本串 S 内查找一个模式串 P 的出现位置 ,这个算法由 Donald Knuth 、 Vaughan Pratt 、 James H. Morris 三人于 1977 年联合发表

    2024年02月07日
    浏览(46)
  • JVM-JVM中对象的生命周期

    申明:文章内容是本人学习极客时间课程所写,文字和图片基本来源于课程资料,在某些地方会插入一点自己的理解,未用于商业用途,侵删。 原资料地址:课程资料 对象的创建 常量池检查 :检查new指令是否能在常量池中定位到这个类的符号引用,检查类之前是否被加载过

    2024年02月20日
    浏览(42)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包