上一篇:一个90后员工猝死的全过程

来源:www.toutiao.com/i6893014573322863111

# 前言

话说Java中String是有长度限制的,听到这里很多人不禁要问,String还有长度限制?是的有,而且在JVM编译中还有规范,而且有的家人们在面试的时候也遇到了。

本人就遇到过面试的时候问这个的,而且在之前开发的中也真实地遇到过这个String长度限制的场景(将某固定文件转码成Base64的形式用字符串存储,在运行时需要的时候在转回来,当时文件比较大),那这个规范限制到底是怎么样的,咱们话不多说先䁖䁖去。

# String

首先要知道String的长度限制我们就需要知道String是怎么存储字符串的,String其实是使用的一个char类型的数组来存储字符串中的字符的。

存储String的容器原来是它

那么String既然是数组存储那数组会有长度的限制吗?是的有限制,但是是在有先提条件下的,我们看看String中返回length的方法。

String类中的length方法

由此我们看到返回值类型是int类型,Java中定义数组是可以给数组指定长度的,当然不指定的话默认会根据数组元素来指定:

int[] arr1 = new int[10]; // 定义一个长度为10的数组int[] arr2 = {1,2,3,4,5}; // 那么此时数组的长度为5

整数在java中是有限制的,我们通过源码来看看int类型对应的包装类Integer可以看到,其长度最大限制为2^31 -1,那么说明了数组的长度是0~2^31-1,那么计算一下就是(2^31-1 = 2147483647 = 4GB)

Integer的取值范围

看到这我们尝试通过编码来验证一下上述观点。

以字面量形式定义字符串

以上是我通过定义字面量的形式构造的10万个字符的字符串,编译之后虚拟机提示报错,说我们的字符串长度过长,不是说好了可以存21亿个吗?为什么才10万个就报错了呢?

其实这里涉及到了JVM编译规范的限制了,其实JVM在编译时,如果我们将字符串定义成了字面量的形式,编译时JVM是会将其存放在常量池中,这时候JVM对这个常量池存储String类型做出了限制,接下来我们先看下手册是如何说的。

java虚拟机规范截图

常量池中,每个 cp_info 项的格式必须相同,它们都以一个表示 cp_info 类型的单字节 “tag”项开头。后面 info[]项的内容 由tag 的类型所决定。

java虚拟机规范手册常量类型表

我们可以看到 String类型的表示是 CONSTANT_String ,我们来看下CONSTANT_String具体是如何定义的。

这里定义的 u2 string_index 表示的是常量池的有效索引,其类型是CONSTANT_Utf8_info 结构体表示的,这里我们需要注意的是其中定义的length我们看下面这张图。

在class文件中u2表示的是无符号数占2个字节单位,我们知道1个字节占8位,2个字节就是16位 ,那么2个字节能表示的范围就是2^16- 1 = 65535 。范中class文件格式对u1、u2的定义的解释做了一下摘要:

这里对java虚拟机规摘要部分

1、class文件中文件内容类型解释

定义一组私有数据类型来表示 Class 文件的内容,它们包括 u1,u2 和 u4,分别代      表了 1、2 和 4 个字节的无符号数。

每个 Class 文件都是由 8 字节为单位的字节流组成,所有的 16 位、32 位和 64 位长度的数      据将被构造成 2 个、4 个和 8 个 8 字节单位来表示。

2、程序异常处理的有效范围解释

start_pc 和 end_pc 两项的值表明了异常处理器在 code[]数组中的有效范围。

start_pc 必须是对当前 code[]数组中某一指令的操作码的有效索引,end_pc 要      么是对当前 code[]数组中某一指令的操作码的有效索引,要么等于 code_length      的值,即当前 code[]数组的长度。start_pc 的值必须比 end_pc 小。

当程序计数器在范围[start_pc, end_pc)内时,异常处理器就将生效。即设 x 为      异常句柄的有效范围内的值,x 满足:start_pc ≤ x < end_pc。

实际上,end_pc 值本身不属于异常处理器的有效范围这点属于 Java 虚拟机历史上      的一个设计缺陷:如果 Java 虚拟机中的一个方法的 code 属性的长度刚好是 65535      个字节,并且以一个 1 个字节长度的指令结束,那么这条指令将不能被异常处理器      所处理。

不过编译器可以通过限制任何方法、实例初始化方法或类初始化方法的code[]数组最大长度为 65534,这样可以间接弥补这个 BUG。

注意:这里对个人认为比较重要的点做了标记,首先第一个加粗说白了就是说数组有效范围就是【0-65565】但是第二个加粗的地方又解释了,因为虚拟机还需要1个字节的指令作为结束,所以其实真正的有效范围是【0-65564】,这里要注意这里的范围仅限编译时期,如果你是运行时拼接的字符串是可以超出这个范围的。

接下来我们通过一个小实验来测试一下我们构建一个长度为65534的字符串,看看是否就能编译通过。

首先通过一个for循环构建65534长度的字符串,在控制台打印后,我们通过自己度娘的一个在线字符统计工具计算了一下确实是65534个字符,如下:

然后我们将字符复制后以定义字面量的形式赋值给字符串,可以看到我们选择这些字符右下角显示的确实是65534,于是乎运行了一波,果然成功了。

看到这里我们来总结一下:

问:字符串有长度限制吗?是多少?

答:首先字符串的内容是由一个字符数组 char[] 来存储的,由于数组的长度及索引是整数,且String类中返回字符串长度的方法length() 的返回值也是int ,所以通过查看java源码中的类Integer我们可以看到Integer的最大范围是2^31 -1,由于数组是从0开始的,所以数组的最大长度可以使【0~2^31】通过计算是大概4GB。

但是通过翻阅java虚拟机手册对class文件格式的定义以及常量池中对String类型的结构体定义我们可以知道对于索引定义了u2,就是无符号占2个字节,2个字节可以表示的最大范围是2^16 -1 = 65535。

其实是65535,但是由于JVM需要1个字节表示结束指令,所以这个范围就为65534了。超出这个范围在编译时期是会报错的,但是运行时拼接或者赋值的话范围是在整形的最大范围。

最后,关注公众号互联网架构师,在后台回复:2T,可以获取我整理和创作的 Java 系列教程非常齐全。

推荐阅读

1、2019 年 9 月全国程序员工资统计,你是什么水平?

2、如何才能成为优秀的架构师?

3、从零开始搭建创业公司后台技术栈

4、程序员一般可以从什么平台接私活?

5、37岁程序员被裁,120天没找到工作,无奈去小公司,结果懵了...

6、滴滴业务中台构建实践,首次曝光

7、不认命,从10年流水线工人,到谷歌上班的程序媛,一位湖南妹子的励志故事

8、15张图看懂瞎忙和高效的区别!

虎牙面试官:String长度有限制吗?是多少?我:这太...相关推荐

  1. 字节面试官推荐的一份 Java 基础面试题!太顶了

    Java 基础篇 Java 有哪些特点 并发性的: 你可以在其中执行许多语句,而不必一次执行它 面向对象的:基于类和面向对象的编程语言. 独立性的: 支持一次编写,到处运行的独立编程语言,即编译后的代 ...

  2. 单例模式双重校验锁_被面试官虐过之后,他轻蔑的问我:你还说你了解单例模式吗?...

    单例,大家肯定都不陌生,这是Java中很重要的一个设计模式.其实单例模式看上去简单,实际上却有很多容易被忽视的地方,因为他涉及到一些线程安全的问题,稍不留神就可能入坑. 本文,就通过一次面试经历来深入 ...

  3. 程序员离职原因的最佳回答_程序员面试被问离职原因,如实回答不适应996,面试官答复尴尬了...

    跳槽面试是一个技术活,特别是面试环节,需要在简短的时间里回答大量问题.如果稍不小心,可能就会导致哭笑不得的结局. 最近,有个程序员就在网上吐槽说,自己原单位加班很严重,长期996(即早上9嗲上班,晚上 ...

  4. 被面试官虐过之后,他轻蔑的问我:你还说你了解单例模式吗?

    单例,大家肯定都不陌生,这是Java中很重要的一个设计模式.其实单例模式看上去简单,实际上却有很多容易被忽视的地方,因为他涉及到一些线程安全的问题,稍不留神就可能入坑. 本文,就通过一次面试经历来深入 ...

  5. 我身家过亿!B站面试官被指炫富歧视北邮学生引爆热搜

    点击上方"AI遇见机器学习",选择"星标"公众号 重磅干货,第一时间送达 来源:zhihu 编辑:yaxin [导读]近日,一则关于B站游戏面试官贬低北邮校招生 ...

  6. B站翻车了? B站面试官:我身家过亿!被指炫富歧视北邮学生上知乎热榜!

    点击上方 "编程技术圈"关注, 星标或置顶一起成长 后台回复"大礼包"有惊喜礼包! 每日英文 Mistakes are part of life. You sh ...

  7. 某程序员吐槽:面试时题做得又快又好,却被面试官挂掉,就因为不承认刷题!...

    为了通过面试,许多人都会大量刷题,但把题都做出来,面试就一定能通过吗? 也未必,一位程序员就因为题做得太好太快,被面试官给挂了-- 他的故事是这样的:面试mid算法题,直接bugfree(无缺陷),面 ...

  8. 软件测试面试官问这些问题的背后意义你知道吗?

    目录 一.谈一下你过去的工作经历?(或者介绍一下你在XX公司的工作) 二.过去工作中曾碰到过什么困难,后来你是怎么解决的? 三.你对自己未来的职业规划有什么想法? 四.为什么你能胜任这个职位? 五.你 ...

  9. arduino char*转string_【201期】面试官:String长度有限制吗?是多少?还好我看过...

    点击上方"Java面试题精选",关注公众号 面试刷图,查缺补漏 >>号外:往期面试题,10篇为一个单位归置到本公众号菜单栏->面试题,有需要的欢迎翻阅 阶段汇总集 ...

  10. 面试官:String的最大长度是多少?

    之前有提到,指北君在做面试相关的事情.有面试官问了String的最大长度是多少?指北君听到这个问题之后有点懵,还好指北君抗住了. 指北君:面试官你好,可以开始面试了吗? 面试官:你好,那我们现在开始吧 ...

最新文章

  1. Vue 中 CSS 动画原理
  2. 搜狗词库爬虫(2):基础爬虫框架的运行流程
  3. 想要挑战成功的hongjin2
  4. UITableViewStyleGrouped顶部留白问题
  5. 编写 iPhone Friendly 的 Web 应用程序 (Part 6 - iUI)
  6. Java中的Collections类– java.util.Collections
  7. mysql5.7误删管理员root账户ERROR1045 (28000): Access denied for user ‘root‘@‘localhost‘ (using password: NO)
  8. 一个素数,如果将其反转后仍然是一个素数,我们称这样的素数为反转素数。 例如13是一个素数,反转之后得到的31也是一个素数,那么13和31都是反转素数。
  9. ubuntu mysql 连接数_ubuntu-阿里云下 Tomcat 应用无法连接数Mysql据库
  10. win10修改计算机物理地址,Windows10系统修改物理地址的方法
  11. 2018一战硕士考研风雨路
  12. 在VMware上搭建iPhone开发环境(转)
  13. PHP输出分割线,dede标签调用大全dedecms隔五行一个分割线_PHP教程
  14. 盛世昊通:广州车展那些出彩的车,你心动了吗?
  15. Day3:现金流三拷问---投资环节
  16. Java 实现数据库数据 导入 导出成Excel文档的功能
  17. HTML 图片鼠标悬停动态效果
  18. 思维模型 DISC色彩性格
  19. 【Linux】嵌入式·NAND Flash
  20. 体验一把 Flowable 三种常见网关

热门文章

  1. 在FL Studio中编辑视频中的音频
  2. SVN的学习和使用(七)——SVN提交操作
  3. SpringBoot Logback配置,SpringBoot日志配置
  4. CentOS 6.5安装Tomcat-9.0.0.M19
  5. 年底购物狂欢,移动支付安全不容忽视
  6. 学习Bloom Filter,处理“海量”数据
  7. linux学习 建立静态库,动态库,写简单的makefile
  8. Microsoft Office2021中文版Mac(office全家桶)
  9. Ps 初学者教程,如何在图片中创建双重曝光效果?
  10. Charles for Mac(抓包工具)