Scanner.findInLine()大量泄漏内存

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方法在填充堆之前累积了数十亿字节的数据.

任何人都能指出我正确的方向吗?

dar*_*met 0

好吧,我找到了问题的根源,它不完全是 Scanner ,而是包含在构造函数中进行扫描的对象的列表。

该问题与包含对包含解析的对象的引用的列表的溢出有关,本质上,每单位时间接收到的字符串多于可以处理的字符串,并且列表不断增长,直到没有更多的 RAM。现在,将此列表限制为最大大小可以防止解析器使内存过载;我将在解析器和数据源之间添加一些同步,以避免将来出现这种溢出情况。

感谢大家的建议,我已经对扫描仪的性能进行了一些更改,并感谢 @RobI 向我指出 jvisualvm,这使我能够追溯到持有引用的确切罪魁祸首。内存转储未显示引用链接。