java 对象实际占用内存大小预估工具类ObjectSizeUtil

java 对象实际占用内存大小预估工具类

返回对象占用预估字节数

返回字节数对应格式化后的字符串(xx Kb)

使用效果
在这里插入图片描述
在这里插入图片描述
依赖了lombock和hutool,项目不用这个可以去掉日志,稍微改写一下。


import cn.hutool.core.util.ClassUtil;
import lombok.extern.slf4j.Slf4j;import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.text.DecimalFormat;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;/*** @author humorchen* date: 2024/4/1* description: 对象大小计算工具**/
@Slf4j
public class ObjectSizeUtil {/*** 嵌套深度不超过10层*/public static int MAX_DEPTH = 10;/*** 单位*/public static final String[] UNIT_NAMES = new String[]{"B", "KB", "MB", "GB", "TB", "PB", "EB"};/*** 字段缓存*/private static final Map<Class<?>, Field[]> FIELD_CACHE = new ConcurrentHashMap<>();/*** 获取对象大小,接近实际内存大小,不完全等于实际大小,用于快速计算内存大小* 性能测试:三层带List的对象,百万次调用,耗时 196ms** @param o* @return*/public static long estimateObjectSize(Object o) {return estimateObjectSize(o, 0);}/*** 获取对象大小,接近实际内存大小,不完全等于实际大小,用于快速计算内存大小* 性能测试:三层带List的对象,百万次调用,耗时 196ms** @param o* @param depth* @return*/private static long estimateObjectSize(Object o, int depth) {if (o == null) {return 4L;}// 深度兜底if (depth >= MAX_DEPTH) {return 4L;}// 基本类型、基本类型包装类、枚举、数组、集合、Map、注解、其他类Class<?> cls = o.getClass();// 64位机器上每个对象至少有16字节的开销long size = 16L;// 基本类和包装对象 int 的class是java.lang.Integerif (ClassUtil.isBasicType(cls)) {if (cls == Integer.class || cls == Float.class) {size += 4L;} else if (cls == Long.class || cls == Double.class) {size += 8L;} else if (cls == Short.class || cls == Byte.class) {size += 2L;} else if (cls == Character.class || cls == Boolean.class) {size += 1L;}} else if (cls == String.class) {// 字符串,每个字符2字节size += 2L * ((String) o).length();} else if (cls.isEnum()) {// 枚举为常量,内存占用视为一个对象引用地址4字节size = 4L;} else if (cls.isAnnotation()) {// 注解 内存占用视为一个对象引用地址4字节size = 4L;} else if (cls.isArray()) {// 数组 遍历数组中的每个元素,递归调用estimateObjectSize方法,数组里每个对象指针4字节int len = Array.getLength(o);for (int i = 0; i < len; i++) {size += estimateObjectSize(Array.get(o, i), depth + 1) + 4;}} else if (o instanceof Collection) {// 集合 遍历集合中的每个元素,递归调用estimateObjectSize方法Collection<?> collection = (Collection<?>) o;if (!collection.isEmpty()) {for (Object obj : collection) {// 集合里每个对象指针4字节size += estimateObjectSize(obj, depth + 1) + 4;}}} else if (o instanceof Map) {// Map 遍历Map中的每个元素,递归调用estimateObjectSize方法Map<?, ?> map = (Map<?, ?>) o;if (!map.isEmpty()) {for (Map.Entry<?, ?> entry : map.entrySet()) {// 集合里每个对象指针4字节 *2size += 8;size += estimateObjectSize(entry.getKey(), depth + 1);size += estimateObjectSize(entry.getValue(), depth + 1);}}} else {// 其他类,遍历类中的每个字段,递归调用estimateObjectSize方法,计算字段的内存占用,field获取每次执行都会拷贝,所以用缓存Field[] declaredFields = FIELD_CACHE.computeIfAbsent(cls, k -> {// 获取类声明的字段,会拷贝Field[]Field[] fields = getDeclaredFields(cls);// 设置可访问for (Field field : fields) {field.setAccessible(true);}return fields;});for (Field declaredField : declaredFields) {try {// 静态的字段直接算一个指针的内存if (Modifier.isStatic(declaredField.getModifiers())) {size += 4L;} else {// 当前字段的这个指针的内存占用加指向的对象内存占用Object object = declaredField.get(o);size += estimateObjectSize(object, depth + 1) + 4;}} catch (Exception e) {log.error("获取对象大小异常", e);}}}return size;}/*** 获取类声明的字段** @param cls* @return*/private static Field[] getDeclaredFields(Class<?> cls) {Set<Field> set = new LinkedHashSet<>();Class<?> currentClass = cls;int depth = 0;while (!Object.class.equals(currentClass) && depth < MAX_DEPTH) {set.addAll(Arrays.asList(currentClass.getDeclaredFields()));currentClass = currentClass.getSuperclass();depth++;}return set.toArray(new Field[0]);}/*** 格式化字节数** @param size* @return*/public static String formatSize(long size) {if (size <= 0) {return "0";}int digitGroups = Math.min(UNIT_NAMES.length - 1, (int) (Math.log10(size) / Math.log10(1024)));return new DecimalFormat("#,##0.##").format(size / Math.pow(1024, digitGroups)) + " " + UNIT_NAMES[digitGroups];}
}

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

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

相关文章

docker怎么拉取全部镜像,打包所有镜像

因为docker&#xff0c;所以我把电脑上之前的镜像全部打包出来了 你们也可以打包&#xff0c;我提供一个脚本&#xff0c;你运行即可 export_docker.sh #!/bin/bash# 导出目录 EXPORT_DIR"docker_images_backup" mkdir -p "$EXPORT_DIR"# 获取所有镜像 …

PythonPoc基础编写(3)---批量刷cnvd

文章目录 前言一、发现过程二、使用步骤1.引入库2.读入数据结果 总结 前言 想刷cnvd&#xff1f;最重要的是登录进行测试功能点 一、发现过程 找到一个网站 发现登录失败返回200 登录成功则是重定向 302 那就写一个脚本吧 二、使用步骤 1.引入库 import requests 2.读入…

安装AutoCAD异常

问题&#xff1a; 安装Autodesk产品时&#xff0c;显示以下消息&#xff0c;且安装未完成。 正在等待操作系统重新启动。 请重新启动计算机以安装 AutoCAD 2024。 操作系统&#xff1a; Windows 10Windows 11 原因&#xff1a; Windows注册表项已损坏。Microsoft Visual C …

微射流均质机可用于纳米制剂和材料制备 我国市场需求空间广阔

微射流均质机可用于纳米制剂和材料制备 我国市场需求空间广阔 微射流均质机是一种纳米级乳化及分散的处理设备&#xff0c;工作原理是在加压状态下&#xff0c;高压流体经过微细孔径喷嘴后&#xff0c;形成高速微射流&#xff0c;从而产生强大的涡流和切应力&#xff0c;将颗粒…

ESP8266-01S烧录MQTT固件ERROR问题

今天在烧录ESP8266固件时遇到了这个问题&#xff0c;技术客服给了个有效的解决方案。 选择固件的时候可以先确认自己的模块是ESP8266或者EPS8285主控&#xff0c;这在选择DOWNLOADTOOL时还不一样。 然后波特率是115200&#xff0c;我在这个地方选错成1152000。 当然上面都不…

【ARM Cache 及 MMU 系列文章 1.4 -- 如何判断 L3 Cache 是否实现?】

请阅读【ARM Cache 及 MMU/MPU 系列文章专栏导读】 及【嵌入式开发学习必备专栏】 文章目录 Cluster Configuration Register代码实现什么是Single-Threaded Core?什么是PE(Processor Execution units)?Single-Threaded Core与PE的关系对比多线程(Multithreading)Cluster…

gridview自带编辑功能如何判断用户修改的值的合法性

在使用GridView的编辑功能更新值时&#xff0c;确保输入的值合法性是十分重要的。为了实现这一点&#xff0c;你可以在GridView的RowUpdating事件中加入代码来检查用户输入的值。如果发现输入的值不合法&#xff0c;你可以取消更新操作并向用户显示错误消息。下面是如何实现的步…

小区噪音监测管理系统设计

一、引言 随着城市化进程的加快&#xff0c;小区居民对于居住环境的要求日益提高。其中&#xff0c;噪音污染已成为影响居民生活质量的重要因素。因此&#xff0c;设计一套小区噪音监测管理系统&#xff0c;对于提升居民的生活品质和小区管理效率具有重要意义。本文将详细阐述…

数据资产驱动的智能化决策:深度剖析数据资产在提升企业决策效率与准确性中的关键作用

在数字化、信息化日益普及的今天&#xff0c;数据已经成为企业发展的重要资产。数据资产不仅能够帮助企业更好地了解市场需求、优化业务流程&#xff0c;还能在决策过程中提供科学、精准的支持。本文将深入剖析数据资产在提升企业决策效率与准确性中的关键作用&#xff0c;探讨…

电脑文件防泄密软件——天锐绿盾 - 中科数安—— 哪个好

在选择电脑文件防泄密软件时&#xff0c;天锐绿盾和中科数安都是值得考虑的选项。以下是对这两款软件的详细比较&#xff1a; www.drhchina.com PC地址&#xff1a; https://isite.baidu.com/site/wjz012xr/2eae091d-1b97-4276-90bc-6757c5dfedee 功能全面性&#xff1a; 天锐…

Java内存模型(JMM)详解

文章目录 1、Java内存模型2、JMM的核心概念1&#xff09;主内存与工作内存2&#xff09;内存可见性3&#xff09;JMM的三大特性&#xff1a;原子性、可见性、有序性。 3、JMM中的八种操作4、Happens-before 规则5、样例&#xff1a; 1、Java内存模型 Java内存模型&#xff08;…

系统安全(补充)

基于行的自主访问控制的方法有能力表、前缀表、口令基于列的自主访问控制的方法有访问控制表、保护位口令是当前大多数网络实施访问控制进行身份鉴别的重要依据&#xff0c;因此&#xff0c;口令管理尤为重要&#xff0c;一般遵守一般遵守以下原则&#xff1a;1口令选择应至少在…

一种可以识别局部单调的系数

记录一种可以识别局部单调的系数 pearson和kendall等系数再识别单调的时候&#xff0c;更多是关注整体情况&#xff0c;很多时候&#xff0c;变量和因变量之间非简单的单调关系&#xff0c;局部单调ξ识别 假设我们正在测量变量X和Y之间的关系。传统的相关性测量方法通常假定…

Go - 3.库源码文件

目录 一.引言 二.库源码文件 1.定义 2.生成库源码文件 3.直接调用库源码文件 三.总结 一.引言 前面我们学习了 命令源码文件&#xff0c;并成功运行了 go 的 hello world 代码&#xff0c;下面我们介绍 go 里面另一个概念: 库源码文件。 二.库源码文件 1.定义 库源码文…

一看就会!Win11文件资源管理器的打开方法!

在Win11电脑操作中&#xff0c;用户可以借助文件资源管理器轻松管理文件或文件夹。但是&#xff0c;许多新手用户不知道要怎么操作才能顺利打开文件资源管理器&#xff1f;接下来小编给大家介绍五种简单快速的打开Win11系统文件资源管理器的方法。 方法 1&#xff1a;WindowsE …

企业邮箱大附件无法上传?无法确认接收状态?这样解决就行

Outlook邮箱作为最常用的邮箱系统&#xff0c;被全世界企业采用作为内部通用沟通方式&#xff0c;但Outlook邮箱却有着明显的使用缺陷&#xff0c;如邮箱大附件上传障碍及附件接收无提示等。 1、企业邮箱大附件无法上传 Outlook企业邮箱大附件的上传上限一般是50M&#xff0c;…

SpringSecurity6从入门到实战之自定义登录页面

SpringSecurity6从入门到实战之自定义登录页面 在使用SpringSecurity进行认证操作的时候,可以发现默认提供的登录页面比较简陋.那么我们能否对登录页面进行自定义配置呢?接下来开始讲解应该如何进行配置 自定义登录页面流程 引入模板依赖 由于自定义登录页面会使用到前端相关…

测试单选框

单选按钮&#xff1a;用于在一组互相排斥的选项中选择其中一项&#xff1b; 由一个圆圈和紧随其后的文本标题组成&#xff0c;当它被选中时&#xff0c;圆圈中就标上一个黑点。 通常将一组单选按钮放在一个组框控件中&#xff0c;在一组单选按钮中&#xff0c;第一个(Tab键顺序…

【Linux】版本

文章目录 linux版本1、linxu技术版本&#xff08;内核版本&#xff09;2、linux商业化版本&#xff08;发行版本&#xff09; 区别 linux版本 1、linxu技术版本&#xff08;内核版本&#xff09; 内核&#xff1a;提供硬件抽象层、硬盘及文件系统控制及多任务功能的系统核心程…

PyTorch与TensorFlow模型互转指南

在深度学习的领域中&#xff0c;PyTorch和TensorFlow是两大广泛使用的框架。每个框架都有其独特的优势和特性&#xff0c;因此在不同的项目中选择使用哪一个框架可能会有所不同。然而&#xff0c;有时我们可能需要在这两个框架之间进行模型的转换&#xff0c;以便于在不同的环境…