文章目录

  • 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结构说明:

限定字符长度java javastring长度限制_java

这里u1表示1个无符号字节,u2表示2个无符号字节。在class文件的常量池数组中,用1个字节的tag=8表示String,接下来的用2个字节表示具体某个CONSTANT_Utf8_info在常量池中的索引

限定字符长度java javastring长度限制_常量池_02

CONSTANT_String_info结构体中的string_index的值指向了CONSTANT_Utf8_info结构体,而字符串的utf-8编码数据就在这个结构体之中

限定字符长度java javastring长度限制_JVM_03

如定义一个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],这里要注意这里的范围仅限编译时期,如果是运行时拼接的字符串是可以超出这个范围的


总结

  1. 运行时拼接或者赋值的话范围是在整形的最大范围,而字符串的内容是由一个字符数组 char[] 来存储的,由于数组的长度及索引是整数,且String类中返回字符串长度的方法length() 的返回值也是int ,所以通过查看java源码中的类Integer我们可以看到Integer的最大范围是2^31 -1,由于数组是从0开始的,所以数组的最大长度可以使[0, 2^31-1],约为4GB
  2. 直接定义字符串字面量的,由于JVM限制,长度为[0, 65534]。

参考:

*面试官:String的长度有限制吗?是多少?