Java 当我尝试获取字符串的字节,但从字符到字节的转换溢出了整数长度时,会发生什么情况?
给定一个长度为Java 当我尝试获取字符串的字节,但从字符到字节的转换溢出了整数长度时,会发生什么情况?,java,runtime-error,Java,Runtime Error,给定一个长度为Integer.MAX_VALUE的字符串,其中包含需要多个字节来表示的字符,例如汉字,如果执行String.getBytes(),会得到什么结果?有什么好的方法可以测试这种类型的错误吗?根据似乎是的,它在中调用“encode”方法,该方法计算给定字符串所需的最大字节数,并以int返回结果。请参阅调用“scale”的“encode”方法 因此,根据确切的结果,您将得到字符串截断(如果结果为正)或完全失败(如果结果为负)。由于我没有将逻辑深入到ArrayEncoder类中,因此在转换
Integer.MAX_VALUE
的字符串,其中包含需要多个字节来表示的字符,例如汉字,如果执行String.getBytes()
,会得到什么结果?有什么好的方法可以测试这种类型的错误吗?根据似乎是的,它在中调用“encode”方法,该方法计算给定字符串所需的最大字节数,并以int返回结果。请参阅调用“scale”的“encode”方法
因此,根据确切的结果,您将得到字符串截断(如果结果为正)或完全失败(如果结果为负)。由于我没有将逻辑深入到ArrayEncoder类中,因此在转换过程中可能还会出现“数组索引超出边界”异常
(链接指向internet上的一些随机源代码副本,可能不是当前代码)
这大概只是理论上感兴趣的——一个20亿字符的字符串不太可能执行得很好。字符串是一个复杂的不可变类。从历史上看,它只保存了UTF-16双字节字符的
char[]
数组。然后String.getBytes(StandardCharsets.UTF_8)
可能确实会被认为溢出了索引范围
但是,现在字符串已经包含一个字节[]值
。这用于压缩其他字符集中的字符串。问题仍然存在,例如,几乎为整数.MAX_值的压缩ISO-8859-1字符串可能在UTF-8中爆炸(即使使用String.tocharray()
)。一个OutOfMemoryException
因此,可能存在一些不同的溢出,但对于UTF16字符到getBytes(UTF-8):
private static final int MAX_INDEX=Integer.MAX_值;
void checkUtf8Bytes(字符串s){
if(s.length()MAX_索引){
抛出IllegalArgumentException();
}
}
需要专用int字节(int代码点){
如果(代码点<128){
返回1;
}否则,如果(代码点…){
...
}
我认为捕捉OutOfMemoryException更容易
请注意,字节中包含UTF-16字符的普通字符串不能再容纳整数.MAX_值/2字节。我要问的问题是如何生成这样一个字符串。我找不到一种方法来生成这么大的字符串。我尝试的每件事都给了我一个错误,如:
Exception in thread "main" java.lang.OutOfMemoryError: Requested array size exceeds VM limit
我能找到的由两个字节字符组成的最长字符串的字节大小略小于Integer.MAX\u VALUE
String foo = "\uD83D".repeat((Integer.MAX_VALUE)/2-1);
这将为您提供一个由1073741822
字符或2147483644
字节组成的字符串。因此,我无法回答比此更长的字符串,但当您尝试通过以下方式将其转换为字节时,此字符串会导致错误:
byte[] blah = foo.getBytes();
您将得到以下错误:
Exception in thread "main" java.lang.NegativeArraySizeException: -1073741830
如果你能想出一个以字节为单位的长字符串,我希望你的表现不会更好。我希望这能回答你的“会发生什么”和“你将如何测试”问题
以下是我的完整测试和输出:
public class Test {
public static void main(String[] args) {
// Display MAX_VALUE
System.out.println(Integer.MAX_VALUE);
// By a bit of trial and error, build the longest two-byte character string possible with String.repeat()
String foo = "\uD83D".repeat((Integer.MAX_VALUE)/2-1);
// Display the number of bytes this string takes to store, which is just short of Integer.MAX_VALUE
System.out.println(foo.length());
System.out.println(foo.length()*2);
// This line craps out even though the String length in bytes is less than Integer.MAX_VALUE
byte[] blah = foo.getBytes();
}
}
结果:
2147483647
1073741822
2147483644
Exception in thread "main" java.lang.NegativeArraySizeException: -1073741830
at java.base/java.lang.StringCoding.encodeUTF8_UTF16(StringCoding.java:910)
at java.base/java.lang.StringCoding.encodeUTF8(StringCoding.java:885)
at java.base/java.lang.StringCoding.encode(StringCoding.java:489)
at java.base/java.lang.String.getBytes(String.java:981)
at Test.main(Test.java:15)
您应该能够捕获在字符串处理过程中可能遇到的任何异常,这可能是在构建字符串而不是将其转换为字节时遇到的。请记住捕获一个可丢弃的
,因为您将遇到的大多数错误将是运行时异常
s,而不是异常
。Throwable
会抓住任何一个。你可能会得到类似的东西。
2147483647
1073741822
2147483644
Exception in thread "main" java.lang.NegativeArraySizeException: -1073741830
at java.base/java.lang.StringCoding.encodeUTF8_UTF16(StringCoding.java:910)
at java.base/java.lang.StringCoding.encodeUTF8(StringCoding.java:885)
at java.base/java.lang.StringCoding.encode(StringCoding.java:489)
at java.base/java.lang.String.getBytes(String.java:981)
at Test.main(Test.java:15)