50 jhat 中 java.lang.String 的实例占用空间为什么是 28 bytes ?

news2025/5/24 6:28:48

前言

 

此问题是 多个 classloader 加载的同类限定名的Class 在 jhat 中显示不全d 同一时期发现的问题  

大致的情况是 看到了 jhat 中统计的各个 oop 的占用空间 似乎是不太能够对的上  

比如 java.lang.String, 在 64bit vm 上面 开启了 UseCompressedOops 之后, 应该是占用 (12 + 4 + 4) + 4[对齐] = 24, 才对 

但是 实际上在 jhat 显示的是 28 bytes 

我们这里来看一下这个问题, 顺便也可以 扩展一些扩展一些其他问题 

可以先看一下 普通对象的内存布局 对象的默认布局

以下部分内容, 截图 若无特殊说明, 基于 jdk8 

测试用例 

测试用例如下, 然后 生成 dump 文件, 使用 jhat 进行分析 

/**
 * Test27MultiClassInClassloader
 *
 * @author Jerry.X.He <970655147@qq.com>
 * @version 1.0
 * @date 2021-12-12 14:27
 */
public class Test27MultiClassInClassloader {

    // Test27MultiClassInClassloader
    public static void main(String[] args) throws Exception {

        List<Object> refs = new ArrayList<>();
        ClassLoader appClassloader = Test27MultiClassInClassloader.class.getClassLoader();
        URL[] classpath = new URL[]{
                new File("/Users/jerry/IdeaProjects/HelloWorld/target/classes").toURI().toURL()
        };
        String[] alwaysParentPattern = new String[]{};
        for (int i = 0; i < 10; i++) {
            ChildFirstClassLoader classLoader = new ChildFirstClassLoader(classpath, appClassloader, alwaysParentPattern);
            Class userClazz = classLoader.loadClass("com.hx.test12.Test27MultiClassInClassloaderUser");
            System.out.println(" the " + i + "th classloader " + Integer.toHexString(userClazz.hashCode()));
            Object userInstance = userClazz.newInstance();
            refs.add(userInstance);
        }

        System.in.read();

    }

}

查看 java.lang.String 的 instances 

呵呵 对了一下 显然不对 

查看 Test27MultiClassInClassloaderUser

呵呵 对了一下 显然不对 

jhat 的 instanceSize 是怎么计算的 ?

大致的计算方式是 oop 的 nonStatic属性 占用的字节数 + 对象头[16字节] 

首先这个计算 是不够精确的, 因为 会存在将 [Word, Short, Byte, Oop] 放在一些场景下产生的 gap 里面[比如 64bit 的 vm, 开启了 UseCompressedOops 之后, 对象头 对齐 16 byte 的 gap]

oop 的 nonStatic属性 占用的字节数 是读取自 dump 文件, 当前 oop 对应的记录, 根据 offset 来直接获取当前 oop 的 nonStatic属性 占用的字节数 

那么 这个数据就是来自于 heapdump 生成的地方了? 

HotspotVM 生成 dump 文件中的 instanceRecord 

 以下截图基于 jdk9 

如下部分是计算 oop 的 instanceSize 的地方 

可以看到的是 oop 相关均是算作 8byte, 但是实际我们 64bit vm 上面 开启了 UseCompressedOops 之后仅占用 4byte 

另外就是 上面提到的 可能有一部分 [Word, Short, Byte, Oop] 是被分配到 gap 里面的 

综上 dump 文件中的 oop 占用空间的计算 是不够精确的, 不可信的 

java.lang.String 的内存布局

对象的默认内存布局 中提到了一些普通的类型的内存布局, allocate_style 为 1 

    // Fields order: longs/doubles, ints, shorts/chars, bytes, oops, padded fields

java.lang.String 等一部分特殊的 InstanceKlass 的 allocate_style 是不相同的 

  // The next classes have predefined hard-coded fields offsets
  // (see in JavaClasses::compute_hard_coded_offsets()).
  // Use default fields allocation order for them.
  if( (allocation_style != 0 || compact_fields ) && _loader_data->class_loader() == NULL &&
      (_class_name == vmSymbols::java_lang_AssertionStatusDirectives() ||
       _class_name == vmSymbols::java_lang_Class() ||
       _class_name == vmSymbols::java_lang_ClassLoader() ||
       _class_name == vmSymbols::java_lang_ref_Reference() ||
       _class_name == vmSymbols::java_lang_ref_SoftReference() ||
       _class_name == vmSymbols::java_lang_StackTraceElement() ||
       _class_name == vmSymbols::java_lang_String() ||
       _class_name == vmSymbols::java_lang_Throwable() ||
       _class_name == vmSymbols::java_lang_Boolean() ||
       _class_name == vmSymbols::java_lang_Character() ||
       _class_name == vmSymbols::java_lang_Float() ||
       _class_name == vmSymbols::java_lang_Double() ||
       _class_name == vmSymbols::java_lang_Byte() ||
       _class_name == vmSymbols::java_lang_Short() ||
       _class_name == vmSymbols::java_lang_Integer() ||
       _class_name == vmSymbols::java_lang_Long())) {
    allocation_style = 0;     // Allocate oops first
    compact_fields   = false; // Don't compact fields
  }

allocate_style 为 0 的场景下面, oops 是放置于 longs/doubles 之前 

对于我们 java.lang.String 来说一个内存编排应该是 

1. private final char value[]; 

2. private int hash;

  int next_nonstatic_oop_offset = 0;
  int next_nonstatic_double_offset = 0;

  // Rearrange fields for a given allocation style
  if( allocation_style == 0 ) {
    // Fields order: oops, longs/doubles, ints, shorts/chars, bytes, padded fields
    next_nonstatic_oop_offset    = next_nonstatic_field_offset;
    next_nonstatic_double_offset = next_nonstatic_oop_offset +
                                    (nonstatic_oop_count * heapOopSize);
  }

然后我们使用常用的工具 jol 来看一下, 一个 "xx" 的 java.lang.String, 可以看到 确实如此 

java.lang.String object internals:
 OFFSET  SIZE     TYPE DESCRIPTION                               VALUE
      0     4          (object header)                           05 00 00 00 (00000101 00000000 00000000 00000000) (5)
      4     4          (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
      8     4          (object header)                           da 02 00 f8 (11011010 00000010 00000000 11111000) (-134216998)
     12     4   char[] String.value                              [x, x]
     16     4      int String.hash                               0
     20     4          (loss due to the next object alignment)
Instance size: 24 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

完 

参考 

对象的默认布局

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/56850.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Gram矩阵+Gram矩阵和协方差矩阵的关系

目录Gram矩阵简介协方差矩阵Gram矩阵 和 协方差矩阵的关系Gram Matrix代码Gram矩阵简介 gram矩阵是计算每个通道 i 的feature map与每个通道 j 的feature map 的内积 gram matrix的每个值可以说是代表 i 通道的feature map和 j 通道的 feature map的互相关程度。 参考博客 GAT…

小程序开发---02认识宿主环境

小程序依赖于微信提供宿主环境 小程序可以借助宿主环境提供的能力&#xff0c;可以完成许多普通网页无法完成的功能&#xff0c;如&#xff1a;微信扫码&#xff0c;微信支付&#xff0c;微信登录&#xff0c;定理定位&#xff0c;etc…等 小程序宿主环境包含以下内容&#xf…

关闭不同型号的 ESP 芯片的 ROM Code 上电启动日志的流程

【说明】 芯片 ROM Code 上电启动日志&#xff0c;不会对应用固件产生任何影响。通过 ROM Code 上电日志能够判断芯片启动模式是处于什么状态。若关闭此日志打印&#xff0c;当芯片进入下载模式或进入 Flash 启动模式等都不会有任何日志提示&#xff0c;不利于检查芯片状态&am…

操作系统学习笔记(V):设备管理

目录 1 设备 1.1 设备的概念 1.2 设备的分类 2 I/O控制器 2.1 I/O控制器 1.定义 2.功能 3.组成 2.2 I/O控制方式 1.程序直接控制方式 2.中断驱动方式 3.DMA方式 4.通道控制方式 5.对比 2.3 I/O软件层次结构 1.用户层软件 2.设备独立性软件 3.设备驱动程序 4…

Windows ssh免密访问Linux服务器

文章目录1.在Windows上生成公钥和私钥2.将公钥中的内容复制到linux服务器3.确认linux服务器开启了允许SSH免密登录4.确认免密登录配置成功ssh提供了安全的身份认证的策略&#xff0c;在免密登录之前&#xff0c;首先需要一对公钥和私钥。客户端拿着私钥&#xff0c;服务端拿着公…

【计算机网络】超详细——华为eNSP的安装教程

网络工程师小白或初次接触计算机网络的学生&#xff0c;网络相关的书本学习起来枯燥乏味&#xff0c;这时需要仿真模拟器来加深对网络知识的理解。目前提供网络仿真平台有cisco、华为等&#xff0c;若您英语基础薄弱建议选华为&#xff0c;英语阅读能力较强的直接上cisco的模拟…

redis我记不住的那些命令(五)

背景&#xff1a;我记不住那么多命令&#xff0c;又是Linux命令&#xff0c;又是Git命令&#xff0c;又是kubernetes的命令&#xff0c;又是maven命令&#xff0c;又是redis命令。所谓好记性不如烂笔头&#xff0c;记下来吧。 一、set集合 集合的特点是 无序且各不相同的元素…

SpringSecurity(二十二)--OAuth2:实现资源服务器(下)通过redis和缓存实现TokenStore

一、前言 本章将在前面几章基础上进行讲解&#xff0c;所以大家最好尽量先去看一下前几章的内容再来跟进会好很多。那么本章我们将通过redis和本地缓存Caffeine对JdbcTokenStore进行重写&#xff0c;并且讲解资源服务器配置的新方案&#xff0c;使得我们可以不用在资源服务器又…

[附源码]计算机毕业设计springboot校园疫情防范管理系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

LeetCode 337. 打家劫舍 III(C++)*

该题也是使用动态规划的思路&#xff0c;主要考虑根节点的最大金额和左右子节点的关系&#xff0c;其中分为两种情况&#xff1a;有该结点有没有偷钱&#xff0c;其次要遵守不报警原则。可得到状态转移方程&#xff1a; f为根节点被选中的最大&#xff0c;g为根节点没被选中的最…

Day17-购物车页面-结算-动态计算已勾选商品的数据和选中状态

1.动态渲染已勾选商品的总数量 我的操作&#xff1a; 1》在 store/cart.js 模块中&#xff0c;定义一个名称为 checkedCount 的 getters&#xff0c;用来统计已勾选商品的总数量&#xff1a; 2》在 my-settle 组件中&#xff0c;通过 mapGetters 辅助函数&#xff0c;将需要的…

[附源码]Python计算机毕业设计Django健身房信息管理

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…

GIS工具maptalks开发手册(五)01-用JSON载入地图——json格式绘制多个面之基础版

GIS工具maptalks开发手册(五)01-用JSON载入地图——json格式绘制多个面之基础版 效果-json渲染图层基础版 代码 index.html <!DOCTYPE html> <html> <meta charset"UTF-8"> <meta name"viewport" content"widthdevice-width,…

HTML5期末考核大作业,网站——旅游景点。 学生旅行 游玩 主题住宿网页

&#x1f389;精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业…

【网络层】流量控制VS拥塞控制、路由器功能、SDN控制平面

文章目录前言网络层功能流量控制VS拥塞控制拥塞控制路由器功能转发---硬件解决------数据平面---------处理数据各种转发路由选择---软件解决---控制平面----控制网络协议运行-------OSPF、RIP、BGP数据平面控制平面---路由选择传统方法-------每路由器法----------路由选择处理…

[附源码]计算机毕业设计疫苗及注射管理系统Springboot程序

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

Ubuntu20.04 通过deb包方式安装微信

写在前面 写文时间&#xff1a;2022.12.03 周六 自己的系统是Ubuntu20.04.5&#xff0c;安装的是 weixin_2.1.1_amd64.deb。 安装微信 从优麒麟官网下载微信deb安装包。 下载完成后&#xff0c;直接安装即可 sudo dpkg -i weixin_2.1.1_amd64.deb参考链接 [1] 优麒麟官网…

基于HFSS的线阵综合分析

摘要&#xff1a; 常规的阵列天线方向图综合是基于阵因子分析法&#xff0c;且不考虑单元之间电磁耦合的一种快速分析手段。本次推文则简单阐述一个基于HFSS的线阵综合实例。 HFSS中的直线阵 均匀直线阵的基础知识已在前面的推文中进行了多次阐述举例&#xff0c;这里就不赘…

正则表达式中的元字符,量词:贪婪和非贪婪,转义符: \s: 记得使用-z --null-data: 使用ascii码中空字符来替换新行,分组:““,和‘‘

正则表达式的所有内容&#xff1a;&#xff08;每一个解释下面都带一个样例&#xff09; 1.元字符 \&#xff1a;忽略后面一个字符的特殊含义 [a-b]&#xff1a;对a到b之间的任何字符进行匹配 ^&#xff1a;在每行的开始进行匹配 $ &#xff1a;在每行的末尾进行匹配 . .&…

FFmpeg编译参数分析

config.mak 来传递给 makefile &#xff0c;还会生成 config.h 给 C 程序 include 引入。 由于 configure 脚本的编译参数是非常多的&#xff0c;本文主要讲解一些比较常用的编译参数&#xff0c;一些特殊的编译参数&#xff0c;读者可通过以下命令查询。 configure --help1&…