Java:对于 Oracle 的 javac 来说代码太大,对于 Eclipse 则不然

Java: Code too large for Oracle's javac is not so for Eclipse

我有一个 Antlr3 生成的 Java lexer/parser 为此 MySQL grammar

Eclipse Neon 可以编译上面的lexer/parser就好了。生成的程序也运行得很好。

但是,Oracle Java 8 编译器对相同的 Java 代码给出了 'code too large' 错误:

[javac] .../MySQLParser.java:27: error: code too large
[javac]     public static final String[] tokenNames = new String[] {
[javac]                                  ^
[javac] 1 error

问题:

  1. 如果正在编译的 Java 代码确实太大(> 64K),两个编译器不应该产生同样的错误吗?

  2. 如果是字节码太大,有什么办法可以让Oracle编译器生成一个space高效的代码,类似于Eclipse的?

    出于代码维护的原因,我既不希望编辑从 Antlr 站点获得的原始 MySQL 语法,也不希望编辑生成的 Java parser/lexer 代码来实现它对于 Oracle 来说足够小。因此,更喜欢一些 "meta"、编译器级别的解决方法。

  3. 上面的错误信息是否意味着问题只是 tokenNames 太大了?或者,是不是它的成员整体class太大了?

tokenNames 单独不太可能产生太大的代码。发生的事情是 class 中的所有变量初始化(包括往往非常大的 DFA 初始化)都被编译成一个静态初始化器,它的行为(在某些方面)像一个普通方法,并且有这段代码大小限制。

当我们 运行 解决这个问题(虽然语法更大)时,我们实际做的是修改生成 Java 解析器的模板,而不是

public static final String[] tokenNames = new String[] { ... };

它生成的代码类似于

public static String[] tokenNames;
static {
    tokenNames = new String[] { ... };
}

(我们实际上是为 DFA 初始化而不是 tokenNames 这样做的,因为那是我们遇到问题的地方)

这涉及修改 ANTLR 工具 - 对于 Eclipse 仍然能够编译它的情况,这可能不是最简单的解决方案。从好的方面来说,它是纯文本修改,只需要一个 zip/unzip 工具和一个文本编辑器,再加上学习 ANTLR 的内部工作原理。