繁体   English   中英

如何延迟正确初始化 Java 中的 static 数组字段

[英]How to lazy correctly initialize a static array field in Java

生成的 Antlr4 词法分析器和解析器有一些内部数据放在堆上,这些数据在解析后不需要释放以清除堆空间并防止 memory 溢出。 我正在使用惰性初始化器来执行此操作,然后将它们删除。 他们中的大多数都很容易做到。

但是,当我这样做时,有一个数组在抱怨。 我需要知道正确的习惯用法。 我只有一个线程(而且我只使用过一次词法分析器/解析器(*除了在测试中,见下文))所以我并不真正关心同步,但我希望有警告/lint free 编译,并且“ findBugs" 不喜欢我使用的代码。

这是我尝试的初始代码:

public class Lexer;
    protected static DFA[] = null; 
...
    public Lexer(CharStream input) {
       if (_decisionToDFA == null) {
          _decisionToDFA = new DFA[_ATN.getNumberOfDecisions()];
          for (int i = 0; i < _ATN.getNumberOfDecisions(); i++) {
              _decisionToDFA[i] = new DFA(_ATN.getDecisionState(i), i);
          }
        }
    }
...
    public void closeLexer() {
       _decisionToDFA = null;
    }

中间尝试进行 static 初始化的代码是 FindBugs 抱怨的代码。 我尝试了以下但没有帮助。

       if (_decisionToDFA == null) {
          // build it here locally
          DFA _local_decisionToDFA[] = new DFA[_ATN.getNumberOfDecisions()];
          for (int i = 0; i < _ATN.getNumberOfDecisions(); i++) {
              _local_decisionToDFA[i] = new DFA(_ATN.getDecisionState(i), i);
          }
        _decisionToDFA = _local_decisionToDFA;  // then just move the reference
        }

*以下:

例外是当我运行单元测试时。 目前只有 2k 多一点的单元测试,每个都解析一些代码片段并遍历生成的解析树并计算一些东西并检查计算是否匹配正确的语义。

不幸的是,词法分析器和解析器为此构建的内部数据(例如,这些 arrays 和一些缓存等)缓慢累积并最终耗尽所有堆空间,导致接近末尾的测试用完 memory,即为什么我需要释放他们。 在生产运行中,每次编译都是一个独立的进程,有自己的地址空间,所以这不会是一个太大的问题。

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)

事实证明,如果您将代码放入 function 中,这似乎可以消除 findBugs 错误消息。

public class Lexer;
    protected static DFA[] = null; 
...
    private DFA[] createDecisionToDFA() {
          // build it here locally
          DFA _local_decisionToDFA[] = new DFA[_ATN.getNumberOfDecisions()];
          for (int i = 0; i < _ATN.getNumberOfDecisions(); i++) {
              _local_decisionToDFA[i] = new DFA(_ATN.getDecisionState(i), i);
          }
        return _local_decisionToDFA;  // then just move the reference
        }

    public Lexer(CharStream input) {
       if (_decisionToDFA == null) {
          _decisionToDFA = createDecisionToDFA();
        }
    }
...
    public void closeLexer() {
       _decisionToDFA = null;
    }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM