Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/358.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 当我尝试获取字符串的字节,但从字符到字节的转换溢出了整数长度时,会发生什么情况?_Java_Runtime Error - Fatal编程技术网

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)