Scanner.findInLine () massages memory

I am running a simple scanner to parse a string, however I found that if the call is frequent enough, I get OutOfMemory errors. This code is called as part of the constructor of an object that is repeatedly created for an array of strings:

Edit: here is the constructor for more information; not much more going on outside of try-catch regarding scanner

   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);
        }
    }

The profiler’s snapshots show that the read (Char) method of Scanner.findInLine () allocates huge amounts of memory while it’s working, when I look at several hundred thousand lines; after a few seconds it is already allocated over 38 MB.

enter image description here

, close() , GC, - , .

- ?

+5
6

, , , , , .

, , , , , , , ; , .

, @RobI jvisualvm, , . .

0

, Pattern :

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

:

sc.findInLine(p);

OOM, .

: java.util.regex - Pattern.compile()?

: , , . , , , , . Scanner ? ; Scanner , . Scanner Pattern , , , Scanner Pattern , .

+2

, , findInLine(). Pattern .

, , , , , . findInLine(), , , , .

Edit:

:

mnemonic = res.group(1).toLowerCase();

, , toLowerCase() this, . , group(int) a substring(), , char[], . , mnemonic char[] .

:

mnemonic = new String(res.group(1).toLowerCase());
+1

, . , scanner.findInLine() . , scanner.reset(). , .

0

JVM, -, . , () , . JVM GC, - - . , " " , .

0

Your problem is that you are looking at several hundred thousand lines and you are passing the template as a string, so you have a new template object for each individual iteration of the loop. You can pull a template out of a loop, for example:

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

    Scanner sc = new Scanner(headerText);
    MatchResult res;

    try {
        sc.findInLine(toMatch);
        res = sc.match();
    } finally {
        sc.close();
    }

Then you will pass the link to the object only toMatchinstead of having the overhead of creating a new template object for each matching attempt. This will fix the leak.

0
source

All Articles