gpt4 book ai didi

java - 这是内存泄漏还是我刚刚达到了内存中可以保留的对象的限制?

转载 作者:行者123 更新时间:2023-12-01 07:36:50 25 4
gpt4 key购买 nike

我有两个大型 CSV 文件,其中包含 Web 应用程序用户验证某些信息所需的数据。我定义了一个 ArrayList< String[] > 并打算将两个文件的内容保留在内存中,这样我就不必在每次用户登录并使用该应用程序时读取它们。

但是,在初始化应用程序并尝试读取第二个文件时,我收到了 java.lang.OutOfMemoryError: Java heap space 错误。 (它很好地完成了第一个文件的读取,但在读取第二个文件时挂起,过了一会儿我得到了这个异常)

读取文件的代码非常简单:

ArrayList<String[]> tokenizedLines = new ArrayList<String[]>();

public void parseTokensFile() throws Exception {
BufferedReader bRead = null;
FileReader fRead = null;

try {
fRead = new FileReader(this.tokensFile);
bRead = new BufferedReader(fRead);
String line;
while ((line = bRead.readLine()) != null) {
tokenizedLines.add(StringUtils.split(line, fieldSeparator));
}
} catch (Exception e) {
throw new Exception("Error parsing file.");
} finally {
bRead.close();
fRead.close();
}
}

我读到Java的split函数在读取大量数据时可能会占用大量内存,因为子字符串函数引用了原始字符串,因此某些字符串的子字符串将占用与原始字符串相同的内存量,即使我们只想要几个字符,所以我做了一个简单的分割函数来尝试避免这种情况:

public String[] split(String inputString, String separator) {
ArrayList<String> storage = new ArrayList<String>();
String remainder = new String(inputString);
int separatorLength = separator.length();
while (remainder.length() > 0) {
int nextOccurance = remainder.indexOf(separator);
if (nextOccurance != -1) {
storage.add(new String(remainder.substring(0, nextOccurance)));
remainder = new String(remainder.substring(nextOccurance + separatorLength));
} else {
break;
}
}

storage.add(remainder);
String[] tokenizedFields = storage.toArray(new String[storage.size()]);
storage = null;

return tokenizedFields;

}
但这给了我同样的错误,所以我想知道这是否不是内存泄漏,而只是我不能在内存中拥有包含如此多对象的结构。一个文件长约 600,000 行,每行 5 个字段,另一个文件长约 900,000 行,每行字段数量大致相同。

完整的堆栈跟踪是:

Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at xxx.xxx.xxx.StringUtils.split(StringUtils.java:16)
at xxx.xxx.xxx.GFTokensFile.parseTokensFile(GFTokensFile.java:36)

那么,在这篇长篇文章之后(抱歉:P),这是分配给我的 JVM 的内存量的限制还是我错过了一些明显的东西并在某处浪费了资源?

最佳答案

在具有 4GB RAM 的 32 位操作系统上,您的 JVM 不会获得超过 2GB 的空间。这是一个上限。

第二个是您启动 JVM 时指定的最大堆大小。查看 -Xmx 参数。

第三个是生活中的事实,您无法将任何 X 单位放入 Y 大小的容器中,其中 X > Y。您知道文件的大小。尝试单独解析每个并查看它们正在消耗什么样的堆。

我建议您下载Visual VM ,安装所有可用的插件,并让它在运行时监视您的应用程序。您将能够看到整个堆、永久代空间、GC 集​​合、哪些对象占用了最多内存等。

获取数据对于所有问题都是无价的,尤其是像这样的问题。没有它,您只是猜测。

关于java - 这是内存泄漏还是我刚刚达到了内存中可以保留的对象的限制?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10863240/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com