首页 文章 精选 留言 我的

精选列表

搜索[日期选择组件],共10000篇文章
优秀的个人博客,低调大师

内存优化篇-String/char[]/byte[]的选择

Java基本数据类型的大小 type size(bits) bytes boolean 8 1 byte 8 1 char 16 2 short 16 2 int 32 4 long 64 8 float 32 4 double 64 8 Java引用的大小 在 32 位的 JVM 上,一个对象引用占用 4 个字节;在 64 位JVM上,占用 8 个字节。 使用 8 个字节是为了能够管理大于 4G 的内存,如果你的程序不需要访问大于 4G 的内存, 可通过-XX:+UseCompressedOops选项,开启指针压缩。从Java 1.6.0_23开始,这个选项默认是开的。 Java对象头的大小 在32位JVM中,对象头的大小为8个字节(4字节的Mark Word+4字节的Klass Pointer). 在64位JVM上,占用16个字节(8字节的Mark Word+8字节的Klass Pointer),因为开启UseCompressedOops,所以实际占用12个字节(8字节的Mark Word+4字节的Klass Pointer) 。参考klass pointer 接下来的内容都基于64位的JVM来展开 Java对象的大小 1、任意Java对象都包含至少12个字节的Object Header。 2、JVM分配内存以8字节为基本单位,如果不满小于8字节,则向8字节的倍数补齐。参考8 byte alignment 思考 Object object = new Object(); 占用多少内存? 数组的大小如何计算? 验证 添加Maven依赖 <dependency> <groupId>org.openjdk.jol</groupId> <artifactId>jol-core</artifactId> <version>0.9</version> </dependency> import org.openjdk.jol.info.ClassLayout; /** * Created by jianpingpan on 2019/1/17. */ public class BasicClass { public static void main(String[] args) throws Exception { System.out.println(ClassLayout.parseClass(Object.class).toPrintable()); System.out.println(ClassLayout.parseClass(String.class).toPrintable()); System.out.println(ClassLayout.parseClass(byte[].class).toPrintable()); System.out.println(ClassLayout.parseClass(char[].class).toPrintable()); } } byte[] 和char[]的 object header为16个字节是因为有4个字节的数组长度。 String / char[] /byte[] 内存大小计算 String a = new String("abc"); String b = new String("abcd"); String c = new String("abc"); 第一行占用JVM内存的大小: 对象大小 = 12字节(object header)+ 4字节 (hash)+ 4字节(数组引用vlaue[]) + 4字节 (padding) 16字节+3*2字节+2字节padding (数组value[]) = 48字节 假设要缓存的字符个数为N。 String的内存大小计算公式 = 40+N*2 +padding char数组的内存大小计算公式=16+N*2+padding 如果用byte数组来存储字符串数据,占用的内存大小X需要分2种情况讨论: 1、如果需要存储的字符全在ASCII码中,一个字符用一个byte就可以存储 (编码方式可选ISO-8859-1/GBK/UTF-8): X = 16+N+padding 2、如果需要存储的字符范围不能被ASCII码覆盖,则需要根据字符范围确定合适的存储方式。 如需要要存储字符集为ASCII+中文字符,则可使用GBK编码: 16+N+padding<X < 16+N*2+padding 如果字符集不能被ASCII码覆盖,并且包含非中文字符,则使用UTF-8编码: 16+N+padding<X<16+6*N+padding 结论: 由此可见,char数组占用的内存大小小于String占用的内存大小。 若存储的字符范围以ASCII码为主,使用byte数组存储优于char数组。 实际使用场景 那么在缓存中可以直接用char[]或byte[]替换String么? 把 Set<String> set = new HashSet<>(); 替换成 Set<byte[]> set = new HashSet<>(); 会怎样呢? 很明显,contains方法、get方法都会失效。因为每个byte[]的hashCode不一样。 我们用下面的这个ByteArray/CharArray封装byte[],再用ByteArray替换String。 /** * Created by jianpingpan on 2019/1/23. */ public class ByteArray { byte[] bytes; public ByteArray(byte[] bytes){ this.bytes = bytes; } @Override public int hashCode() { if(null == bytes){ return 0; } return new String(bytes).hashCode(); } @Override public boolean equals(Object obj) { if(obj == null){ return false; } return hashCode()==obj.hashCode(); } } (CharArray的实现方式同ByteArray,只是把byte[] bytes 替换成 char[] chars即可) ByteArray占用的内存大小= 12字节(object header+ 4字节(数组引用bytes[]) + 16字节+N字节+padding (数组bytes[]) = 32字节+N字节+padding CharArray占用的内存大小= 12字节(object header+ 4字节(数组引用bytes[]) + 16字节+2*N字节+padding (数组bytes[]) = 32字节+2*N字节+padding 其中,N为数组中元素的个数。 例子 以存储100万条长度为32位的MD5字符串为例且内容互不相同字符串为例(假设字符串中的字符均为字母、数字、下划线)。 可以用classmexer来计算内存使用量 。 import com.javamex.classmexer.MemoryUtil; /** * Created by jianpingpan on 2019/1/25. */ public class StringTest { public static void main(String[] args){ String s="cfcd208495d565ef66e7dff9f98764da"; ByteArray b = new ByteArray(s.getBytes()); CharArray c = new CharArray(s.toCharArray()); long stringBytes = MemoryUtil.deepMemoryUsageOf(s); long byteArrayBytes = MemoryUtil.deepMemoryUsageOf(b); long charArrayBytes = MemoryUtil.deepMemoryUsageOf(c); System.out.println("stringBytes:"+stringBytes); System.out.println("byteArrayBytes:"+byteArrayBytes); System.out.println("charArrayBytes:"+charArrayBytes); } } 用String存储,每条记录占用的空间为 40+32*2 = 104字节 用ByteArray存储,每条记录占用的空间为 32+32 = 64字节 用CharArray存储,每条记录占用的空间为 32+32*2 = 96字节 参考文档: http://btoddb-java-sizing.blogspot.com/2012/01/object-sizes.html https://stackoverflow.com/questions/26357186/what-is-in-java-object-header/26416983 http://openjdk.java.net/groups/hotspot/docs/HotSpotGlossary.html

优秀的个人博客,低调大师

个人如何选择阿里云服务器

如今上云服务器已经成为企业和个人部署站点的首选,成本非常低,可以升降配。阿里的云市场有各种业务的解决方案。阿里云最近推出了云服务器活动,ECS云服务器2折起,优惠配置多选1 阿里云服务器详情入口 https://promotion.aliyun.com/ntms/act/qwbk.html?spm=5176.11770831.1155817.2.9fc7607cwRynJQ&userCode=ffm5f6sd#/ 限时优惠劵 https://promotion.aliyun.com/ntms/yunparter/invite.html?userCode=ffm5f6sd 入门级配置 性能均衡配置 同时支持多种类型的操作系统和带宽 实名认证后新老用户均可购买,限购1单,第2单起恢复原价;时长越长越优惠,新用户可买3台。 说明 参与门槛:新老会员

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

用户登录
用户注册