有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

在ANTLR中解析错误输入时发生java OutOfMemoryError

实际上,这个问题与我之前的问题Catching ANTLR's NoViableAltException in Java and ANTLRWorks Debugger有关,但我决定将它们分开,因为症状不同

问题在于如何将输入文本馈送到ANTLR,其中包含未知标记。例如,我们的语法不知道任何关于从{{CD1}}符号开始的令牌。如果我们试图将这样的文本提供给ANTLRWorks解释器,我们将在结果图中收到NoViableAltException

但是,如果我们使用Java生成和编译的语法并尝试用它解析这些无效文本,我们可以收到以下结果之一(这取决于我们将把这个未知标记放在哪里,即我们将把它放在文本中的“深度”):

1)没有错误,顶级CommonTree对象中的chidlren字段中的null值(提到的问题正是关于这种情况的)

2)java.lang.OutOfMemoryError: Java heap space错误

这个问题是关于第二个案例的。我们如何防止ANTLR解析器的这种行为?例如,在生产环境中,客户端可能会向DSL解析器提供错误的字符序列,从而意外地导致系统崩溃


共 (1) 个答案

  1. # 1 楼答案

    当lexer包含可以匹配空字符串的规则时,通常会发生这种情况。例如,考虑下面的规则:

    WS : (' ' | '\t')*;
    

    此规则可以创建一个WS标记,该标记总共包含0个空格和/或制表符,这意味着在输入中的任何其他标记之间可以有无限多个空格和/或制表符。在某些涉及无效输入的情况下,错误恢复过程可能会被强制进入无限循环,该循环将缓冲令牌,直到Java耗尽内存

    解决这种情况的第一步是检查每个lexer规则,以确保不会发生这种情况。相反WS应该这样写,以确保使用至少1个空格和/或制表符

    WS : (' ' | '\t')+;
    

    PS:Antlr4对语法执行静态检查,如果发生这种情况,将生成错误(4.0)或警告(4.0.1+)