文章目录
- String数据结构限制
- JVM规范限制
- 总结
String数据结构限制
Java中String用char value[]
存储:
/** The value is used for character storage. */
private final char value[];
String长度length()
取自数组长度,返回类型是int
/**
* Returns the length of this string.
* The length is equal to the number of <a href=" ">Unicode
* code units</a > in the string.
*
* @return the length of the sequence of characters represented by this
* object.
*/
public int length() {
return value.length;
}
从这方面看,String的长度上限应该是Java中int
的上限,即 2^31 - 1 = 2147483647,在Java中 char
类型占2 byte(Character.BYTES = 2),因此String最大占用 2 * (2^31 - 1) = 2^32 - 2,约为4GB
JVM规范限制
如果String定义成字面量的形式时,JVM编译时,String会被存放在常量池中
//字面量
String name = "巴勃罗·迭戈·何塞·弗朗西斯科·狄·保拉·胡安·纳波穆西诺·玛莉亚·狄·洛斯·雷梅迪奥斯·西普里亚诺·狄·拉·圣地西玛·特里尼达·路易斯·毕加索";
而JVM对常量池中存放的数据是有限制的,String的常量池项类型CONSTANT_String_info结构说明:
这里u1
表示1个无符号字节,u2
表示2个无符号字节。在class文件的常量池数组中,用1个字节的tag
=8表示String
,接下来的用2个字节表示具体某个CONSTANT_Utf8_info
在常量池中的索引
CONSTANT_String_info
结构体中的string_index
的值指向了CONSTANT_Utf8_info
结构体,而字符串的utf-8编码数据就在这个结构体之中
如定义一个Java类文件 StringConstant.java:
package com.wkw.comprehensive.jdk;
public class StringConstant {
private static String a = "test1";
private String b = "test2";
public static void main(String[] args) {
System.out.println("test3");
}
}
JVM编译为class文件StringConstant.class,使用javap -verbose StringConstant.class
输出class文件具体内容:
Classfile /Users/developmac/workspace/develop/ideaWorkspace/comprehensive-learning/src/main/com/wkw/comprehensive/jdk/StringConstant.class
Last modified 2021-6-10; size 605 bytes
MD5 checksum b45b97cee3142d0b2df8ad70a9ed8487
Compiled from "StringConstant.java"
public class com.wkw.comprehensive.jdk.StringConstant
minor version: 0
major version: 52
flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
#1 = Methodref #10.#23 // java/lang/Object."<init>":()V
#2 = String #24 // test2
......
#24 = Utf8 test2
......
可以看到常量池中索引为2的常量是一个String
,它指向了常量池中索引为24的常量为test2
综上所述,字符串字面量的长度应该是CONSTANT_Utf8_info
.length
最大能表示的范围:2个无符号字节大小,即 2^16-1=65535
但是JVM还需要1个字节的指令作为结束,所以其实真正的有效范围是[0, 65564],这里要注意这里的范围仅限编译时期,如果是运行时拼接的字符串是可以超出这个范围的。
总结
- 运行时拼接或者赋值的话范围是在整形的最大范围,而字符串的内容是由一个字符数组 char[] 来存储的,由于数组的长度及索引是整数,且String类中返回字符串长度的方法length() 的返回值也是int ,所以通过查看java源码中的类Integer我们可以看到Integer的最大范围是2^31 -1,由于数组是从0开始的,所以数组的最大长度可以使[0, 2^31-1],约为4GB;
- 直接定义字符串字面量的,由于JVM限制,长度为[0, 65534]。
参考: