dar*_*met 5 java memory-leaks java.util.scanner
我正在运行一个简单的扫描程序来解析一个字符串,但是我发现如果经常调用,我会得到OutOfMemory错误.此代码作为对象的构造函数的一部分调用,该对象是为字符串数组重复构建的:
编辑:这是更多信息的构造函数; 关于Scanner的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);
}
}
Run Code Online (Sandbox Code Playgroud)
分析器内存快照显示Scanner.findInLine()的读取(Char)方法在操作期间分配大量内存,因为我扫描了几十万个字符串; 几秒钟后它已经分配超过38MB.

我认为在构造函数中使用它之后在扫描程序上调用close()会标记要由GC清除的旧对象,但不知何故它仍然存在并且read方法在填充堆之前累积了数十亿字节的数据.
任何人都能指出我正确的方向吗?
好吧,我找到了问题的根源,它不完全是 Scanner ,而是包含在构造函数中进行扫描的对象的列表。
该问题与包含对包含解析的对象的引用的列表的溢出有关,本质上,每单位时间接收到的字符串多于可以处理的字符串,并且列表不断增长,直到没有更多的 RAM。现在,将此列表限制为最大大小可以防止解析器使内存过载;我将在解析器和数据源之间添加一些同步,以避免将来出现这种溢出情况。
感谢大家的建议,我已经对扫描仪的性能进行了一些更改,并感谢 @RobI 向我指出 jvisualvm,这使我能够追溯到持有引用的确切罪魁祸首。内存转储未显示引用链接。
| 归档时间: |
|
| 查看次数: |
835 次 |
| 最近记录: |