gpt4 book ai didi

java - Scanner.findInLine() 大量泄漏内存

转载 作者:搜寻专家 更新时间:2023-10-31 20:21:26 24 4
gpt4 key购买 nike

我正在运行一个简单的扫描器来解析一个字符串,但是我发现如果经常调用我会得到 OutOfMemory 错误。此代码作为为字符串数组重复构建的对象的构造函数的一部分调用:

编辑:这是更多信息的构造函数;在关于扫描仪的 try-catch 之外没有更多的事情发生

   public Header(String headerText) {
char[] charArr;
charArr = headerText.toCharArray();
// Check that all characters are printable characters
if (charArr.length > 0 && !commonMethods.isPrint(charArr)) {
throw new IllegalArgumentException(headerText);
}
// Check for header suffix
Scanner sc = new Scanner(headerText);
MatchResult res;
try {
sc.findInLine("(\\D*[a-zA-Z]+)(\\d*)(\\D*)");
res = sc.match();
} finally {
sc.close();
}

if (res.group(1) == null || res.group(1).isEmpty()) {
throw new IllegalArgumentException("Missing header keyword found"); // Empty header to store
} else {
mnemonic = res.group(1).toLowerCase(); // Store header
}
if (res.group(2) == null || res.group(2).isEmpty()) {
suffix = -1;
} else {
try {
suffix = Integer.parseInt(res.group(2)); // Store suffix if it exists
} catch (NumberFormatException e) {
throw new NumberFormatException(headerText);
}
}
if (res.group(3) == null || res.group(3).isEmpty()) {
isQuery= false;
} else {
if (res.group(3).equals("?")) {
isQuery = true;
} else {
throw new IllegalArgumentException(headerText);
}
}

// If command was of the form *ABC, reject suffixes and prefixes
if (mnemonic.contains("*")
&& suffix != -1) {
throw new IllegalArgumentException(headerText);
}
}

分析器内存快照显示 Scanner.findInLine() 的 read(Char) 方法在运行期间被分配了大量内存,因为我扫描了几十万个字符串;几秒钟后,它已经分配了超过 38MB。

enter image description here

我认为在构造函数中使用它之后在扫描器上调用 close() 会将旧对象标记为由 GC 清除,但不知何故它仍然存在并且读取方法在填充堆之前累积了千兆字节的数据。

谁能指出我正确的方向?

最佳答案

您还没有发布所有代码,但考虑到您正在重复扫描相同的正则表达式,预先编译静态 Pattern 并将其用于扫描器的查找会更有效:

static Pattern p = Pattern.compile("(\\D*[a-zA-Z]+)(\\d*)(\\D*)");

在构造函数中:

sc.findInLine(p);

这可能是也可能不是 OOM 问题的根源,但它肯定会使您的解析速度更快一些。

相关:java.util.regex - importance of Pattern.compile()?

更新:在您发布更多代码后,我发现了一些其他问题。如果您重复调用此构造函数,则意味着您可能预先对输入进行了标记化或分解。为什么要创建一个新的 Scanner 来解析每一行?它们是昂贵的;如果可能的话,您应该使用相同的 Scanner 来解析整个文件。使用带有预编译 PatternScanner 将比您现在正在做的要快得多,后者正在创建一个新的 Scanner 和一个新的 您要解析的每一行的模式

关于java - Scanner.findInLine() 大量泄漏内存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15554392/

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