title: How to lazy correctly initialize a static array field in Java
body: <p>The generated Antlr4 lexers and parsers have some internal data they put on the heap which isn't necessary after parsing that I want to free up to clear heap space and prevent memory overflows.  I am using lazy initializers to do so and then delete them afterward.  Most of them were easy to do.</p>
  <p>However there is an array that is complaining when I do so.  I need to know the correct idiom for doing it.  I only have one thread (and I only use the lexer/parser once (*except for in testing, see below)) so I'm not really concerned about synchronization, but I would like to have warning/lint free compiles, and &quot;findBugs&quot; doesn't like the code I am using.</p>
  <p>Here is the initial code I tried:</p>
  <pre><code>public class Lexer;
      protected static DFA[] = null; 
  ...
      public Lexer(CharStream input) {
         if (_decisionToDFA == null) {
            _decisionToDFA = new DFA[_ATN.getNumberOfDecisions()];
            for (int i = 0; i &lt; _ATN.getNumberOfDecisions(); i++) {
                _decisionToDFA[i] = new DFA(_ATN.getDecisionState(i), i);
            }
          }
      }
  ...
      public void closeLexer() {
         _decisionToDFA = null;
      }
  </code></pre>
  <p>The code in the middle which attempts to do the static initialization is the code FindBugs complains about.  I tried the following but it didn't help.</p>
  <pre><code>       if (_decisionToDFA == null) {
            // build it here locally
            DFA _local_decisionToDFA[] = new DFA[_ATN.getNumberOfDecisions()];
            for (int i = 0; i &lt; _ATN.getNumberOfDecisions(); i++) {
                _local_decisionToDFA[i] = new DFA(_ATN.getDecisionState(i), i);
            }
          _decisionToDFA = _local_decisionToDFA;  // then just move the reference
          }
  </code></pre>
  <p>*below:</p>
  <p>The exception is when I am running unit tests.  The unit tests of which there are currently just a little over 2k, each parse some fragment of code and the walk the generated parse tree and compute something and check that the computation matches the proper semantics.</p>
  <p>Unfortunately, the internal data (e.g. these arrays and some caches, etc.) that the lexer and parser build to do so, slowly accumulates and eventually uses up all the heap space causing the tests near the end to run out of memory, which is why I need to free them.  In production runs, each compilation is a separate process with its own address space, so it wouldn't be as much an issue.</p>
  <pre><code>Description Resource    Path    Location    Type
  Incorrect lazy initialization and update of static field Lexer._decisionToDFA in new Lexer(CharStream) [Scary(6), High confidence]  PowerShellLexer.java    /src/main/java/Lexer    line 413    FindBugs Problem (Scary)
  </code></pre>