[英]String's Maximum length in Java - calling length() method
在Java 中,參考length()
方法調用, String
對象可能具有的最大大小是多少?
我知道length()
將String
的大小作為char []
;
考慮到String
類的length
方法返回一個int
,該方法返回的最大長度將為Integer.MAX_VALUE
,即2^31 - 1
(或大約 20 億)。
在數組的長度和索引方面,(例如char[]
,這可能是為String
s 實現內部數據表示的方式),第 10 章: Java 語言規范的數組,Java SE 7 版說如下:
數組中包含的變量沒有名稱; 相反,它們由使用非負整數索引值的數組訪問表達式引用。 這些變量稱為數組的組件。 如果一個數組有
n
分量,我們說n
是數組的長度; 使用從0
到n - 1
整數索引引用數組的組件。
此外,索引必須是int
值,如第 10.4 節所述:
數組必須由
int
值索引;
因此,似乎限制確實是2^31 - 1
,因為這是非負int
值的最大值。
但是,可能會有其他限制,例如數組的最大可分配大小。
java.io.DataInput.readUTF()
和java.io.DataOutput.writeUTF(String)
表示String
對象由兩個字節的長度信息和字符串中每個字符的修改后的 UTF-8表示表示。 這得出結論,當與DataInput
和DataOutput
一起使用時,String 的長度受字符串的修改后的 UTF-8 表示的字節數限制。
另外,Java虛擬機規范中CONSTANT_Utf8_info
規范定義了如下結構。
CONSTANT_Utf8_info {
u1 tag;
u2 length;
u1 bytes[length];
}
你可以發現'length'的大小是兩個字節。
某個方法(例如String.length()
)的返回類型是int
並不總是意味着其允許的最大值是Integer.MAX_VALUE
。 相反,在大多數情況下,選擇int
只是出於性能原因。 Java 語言規范說,大小小於int
的int
在計算之前會轉換為int
(如果我沒記錯的話),這也是在沒有特殊原因時選擇int
原因之一。
編譯時的最大長度最多為 65536。再次注意,長度是修改后的 UTF-8表示的字節數,而不是String
對象中的字符數。
String
對象在運行時可能有更多的字符。 但是,如果要使用帶有DataInput
和DataOutput
接口的String
對象,最好避免使用太長的String
對象。 當我實現DataInput.readUTF()
和DataOutput.writeUTF(String)
Objective-C 等價物時,我發現了這個限制。
由於數組必須以整數作為索引,因此數組的最大長度為Integer.MAX_INT
(2 31 -1 或 2 147 483 647)。 當然,這是假設您有足夠的內存來容納該大小的數組。
我有一台帶有 8GB RAM 的 2010 iMac,運行 Eclipse Neon.2 Release (4.6.2) 和 Java 1.8.0_25。 使用 VM 參數 -Xmx6g,我運行了以下代碼:
StringBuilder sb = new StringBuilder();
for (int i = 0; i < Integer.MAX_VALUE; i++) {
try {
sb.append('a');
} catch (Throwable e) {
System.out.println(i);
break;
}
}
System.out.println(sb.toString().length());
這打印:
Requested array size exceeds VM limit
1207959550
因此,最大數組大小似乎是 ~1,207,959,549。 然后我意識到我們實際上並不關心 Java 是否耗盡內存:我們只是在尋找最大數組大小(這似乎是在某處定義的常量)。 所以:
for (int i = 0; i < 1_000; i++) {
try {
char[] array = new char[Integer.MAX_VALUE - i];
Arrays.fill(array, 'a');
String string = new String(array);
System.out.println(string.length());
} catch (Throwable e) {
System.out.println(e.getMessage());
System.out.println("Last: " + (Integer.MAX_VALUE - i));
System.out.println("Last: " + i);
}
}
哪個打印:
Requested array size exceeds VM limit
Last: 2147483647
Last: 0
Requested array size exceeds VM limit
Last: 2147483646
Last: 1
Java heap space
Last: 2147483645
Last: 2
因此,最大值似乎是 Integer.MAX_VALUE - 2 或 (2^31) - 3
PS 我不知道為什么我的StringBuilder
在1207959550
達到最大值,而我的char[]
在 (2^31)-3 達到最大值。 似乎AbstractStringBuilder
將其內部char[]
的大小加倍以增大它,因此這可能會導致問題。
String 類的 length() 方法的返回類型是int 。
公共整數長度()
參考http://docs.oracle.com/javase/7/docs/api/java/lang/String.html#length()
所以 int 的最大值是2147483647 。
String在內部被認為是char數組,所以索引是在最大范圍內完成的。 這意味着我們不能索引第 2147483648 個成員。所以 java 中 String 的最大長度是 2147483647。
java中的原始數據類型int是4個字節(32位)。由於1位(MSB)用作符號位,范圍被限制在-2^31到2^31-1 (-2147483648到2147483647)內。 我們不能為索引使用負值。所以顯然我們可以使用的范圍是從 0 到 2147483647。
顯然它綁定到一個整數,即 0x7FFFFFFF (2147483647)。
正如Takahiko Kawasaki 的回答中提到的,java 以修改后的 UTF-8的形式表示 Unicode 字符串,在 JVM-Spec CONSTANT_UTF8_info Structure 中,2 個字節被分配給長度(而不是字符串的字符數)。
為了擴展答案, ASM jvm 字節碼庫的putUTF8
方法包含以下內容:
public ByteVector putUTF8(final String stringValue) {
int charLength = stringValue.length();
if (charLength > 65535) {
// If no. of characters> 65535, than however UTF-8 encoded length, wont fit in 2 bytes.
throw new IllegalArgumentException("UTF8 string too large");
}
for (int i = 0; i < charLength; ++i) {
char charValue = stringValue.charAt(i);
if (charValue >= '\u0001' && charValue <= '\u007F') {
// Unicode code-point encoding in utf-8 fits in 1 byte.
currentData[currentLength++] = (byte) charValue;
} else {
// doesnt fit in 1 byte.
length = currentLength;
return encodeUtf8(stringValue, i, 65535);
}
}
...
}
但是當代碼點映射 > 1byte 時,它會調用encodeUTF8
方法:
final ByteVector encodeUtf8(final String stringValue, final int offset, final int maxByteLength /*= 65535 */) {
int charLength = stringValue.length();
int byteLength = offset;
for (int i = offset; i < charLength; ++i) {
char charValue = stringValue.charAt(i);
if (charValue >= 0x0001 && charValue <= 0x007F) {
byteLength++;
} else if (charValue <= 0x07FF) {
byteLength += 2;
} else {
byteLength += 3;
}
}
...
}
從這個意義上說,最大字符串長度為 65535 字節,即 utf-8 編碼長度。 而不是char
數
您可以從上面的 utf8 結構鏈接中找到 JVM 的修改后的 Unicode 代碼點范圍。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.