OutOfMemoryError: Java heap space when casting a numeric primitive to char
OutOfMemoryError: Java heap space when casting a numeric primitive to char
一直在研究Decorator模式,开发了简单的classToUpperCaseInputStream。我覆盖了 read() 方法,因此它可以将所有字符从 InputStream 转换为大写。该方法的代码如下所示(抛出 OutOfMemoryError):
@Override
public int read() throws IOException {
return Character.toUpperCase((char)super.read());
}
后来我发现,转换为 char 是多余的,但这不是重点。我有 "java.lang.OutOfMemoryError: Java heap space" 当代码:
((char) super.read())
评价。为了使这个更简单,我写了同样的方法(这个抛出 OutOfMemoryError):
@Override
public int read() throws IOException {
int c =(char) super.read();
return (c == -1 ? c : Character.toUpperCase(c));
}
而这个没有:
@Override
public int read() throws IOException {
int c = super.read();
return (c == -1 ? c : Character.toUpperCase(c));
}
当我从作业中删除强制转换时,代码运行时没有错误,并且所有文本都大写。正如 Oracle 教程中所说:
对引用类型数组组件的赋值(§15.26.1),方法调用表达式(§15.12),或前缀或后缀增量(§15.14.2,§15.15.1)或减量运算符(§15.14.3,§15.15.2)可能所有抛出一个OutOfMemoryError 由于装箱转换 (§5.1.7).
好像是用了自动装箱,但是我的情况不是这样。同一方法的两种变体都会导致 OutOfMemoryError。如果我错了,请给我解释一下,因为它会炸毁我的脑袋。
要提供更多信息,请使用客户端代码:
public class App {
public static void main(String[] args) throws IOException {
try (InputStream inet = new ToUpperCaseInputStream(new FileInputStream("d:/TEMP/src.txt"));
FileOutputStream buff = new FileOutputStream("d:/TEMP/dst.txt")) {
copy(inet, buff);
}
}
public static void copy(InputStream src, OutputStream dst) throws IOException {
int elem;
while ((elem = src.read()) != -1) {
dst.write(elem);
}
}
}
它所做的只是将简单的消息从一个文件打印到另一个文件。
虽然案件已经解决,但我想分享一个关于如何完成转换的非常好的解释。
在转换为 char 之前,您需要检查 -1(表示输入数据结束)。
Java 中的 char 是一个无符号的短整型,这意味着当返回 -1 时,您的转换将使它成为 65535。即使您没有 OutOfMemory,您的代码仍然是错误的。
关于为什么会出现 OOM 错误,如果没有完整的代码就很难说,也许在代码的后面有一些基于字符值的内存分配。
所以试试这个,看看是否有帮助:
@Override
public int read() throws IOException {
int c = super.read();
if (c == -1) return c;
char ch = (char) c;
return Character.toUpperCase(ch);
}
一直在研究Decorator模式,开发了简单的classToUpperCaseInputStream。我覆盖了 read() 方法,因此它可以将所有字符从 InputStream 转换为大写。该方法的代码如下所示(抛出 OutOfMemoryError):
@Override
public int read() throws IOException {
return Character.toUpperCase((char)super.read());
}
后来我发现,转换为 char 是多余的,但这不是重点。我有 "java.lang.OutOfMemoryError: Java heap space" 当代码:
((char) super.read())
评价。为了使这个更简单,我写了同样的方法(这个抛出 OutOfMemoryError):
@Override
public int read() throws IOException {
int c =(char) super.read();
return (c == -1 ? c : Character.toUpperCase(c));
}
而这个没有:
@Override
public int read() throws IOException {
int c = super.read();
return (c == -1 ? c : Character.toUpperCase(c));
}
当我从作业中删除强制转换时,代码运行时没有错误,并且所有文本都大写。正如 Oracle 教程中所说:
对引用类型数组组件的赋值(§15.26.1),方法调用表达式(§15.12),或前缀或后缀增量(§15.14.2,§15.15.1)或减量运算符(§15.14.3,§15.15.2)可能所有抛出一个OutOfMemoryError 由于装箱转换 (§5.1.7).
好像是用了自动装箱,但是我的情况不是这样。同一方法的两种变体都会导致 OutOfMemoryError。如果我错了,请给我解释一下,因为它会炸毁我的脑袋。
要提供更多信息,请使用客户端代码:
public class App {
public static void main(String[] args) throws IOException {
try (InputStream inet = new ToUpperCaseInputStream(new FileInputStream("d:/TEMP/src.txt"));
FileOutputStream buff = new FileOutputStream("d:/TEMP/dst.txt")) {
copy(inet, buff);
}
}
public static void copy(InputStream src, OutputStream dst) throws IOException {
int elem;
while ((elem = src.read()) != -1) {
dst.write(elem);
}
}
}
它所做的只是将简单的消息从一个文件打印到另一个文件。
虽然案件已经解决,但我想分享一个关于如何完成转换的非常好的解释。
在转换为 char 之前,您需要检查 -1(表示输入数据结束)。
Java 中的char 是一个无符号的短整型,这意味着当返回 -1 时,您的转换将使它成为 65535。即使您没有 OutOfMemory,您的代码仍然是错误的。
关于为什么会出现 OOM 错误,如果没有完整的代码就很难说,也许在代码的后面有一些基于字符值的内存分配。
所以试试这个,看看是否有帮助:
@Override
public int read() throws IOException {
int c = super.read();
if (c == -1) return c;
char ch = (char) c;
return Character.toUpperCase(ch);
}