簡體   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