定义一个巨大的全局 ImmutableList 常量的优雅方式(超出堆栈大小限制)

Elegant way to define a huge global ImmutableList constant (beyond stack size limitation)

我正在尝试定义一个全局常量 ImmutableList,它对于默认堆栈大小限制来说太大了,我想知道除了传递积极的 Xss32M 标志之外是否还有其他方法可以解决这个问题至 java.

这是代码片段:

import com.google.common.collect.ImmutableList;
import util.FixedRowDefinition;
import java.util.List;

public class FancyConstants {
    public static final List<Person> student_list = new ImmutableList.Builder<Person>()
        .add(new Person("Amy",12,56))
        .add(new Person("Tom",26,79))
        .........
        .add(...).build()

    /* More similar definitions; could be very long */
}

像上面这样大概有2000行,我猜class炸毁的原因是每个元素都是一个对象(虽然很精简)。

有没有一种方法可以让我在 Java 中定义 student_list,这样它就不会像我目前观察到的那样导致 Whosebug 错误?

您观察到的 Whosebug 错误是由于构建器模式中的调用链造成的。您可以通过在静态初始化程序中添加一个变量来避免它:

public class FancyConstants {
    public static final List<Person> student_list;
    static {
        ImmutableList.Builder<Person> builder = new ImmutableList.Builder<Person>();
        builder.add(new Person("Amy",12,56));
        builder.add(new Person("Tom",26,79));
        .........
        /* More similar definitions; could be very long */
        builder.add(...);
        student_list = builder.build();
    }
}

显然,这不是很优雅,但它修复了 Stack Overflow 错误。

您可以通过从文件中读取数据来改进这种方法,该文件可以作为资源嵌入到您的 Java 程序中。

This Q&A 解释了如何从嵌入式资源中读取。由于您的程序拥有资源的内容,因此您可以使用少量代码填充 builder,并且几乎没有错误检查。

要回答您原来的问题,您可以使用 -J 选项将 JVM 选项传递给 javac。例如。我采用了您的代码模板,创建了 3600 次调用链,并使用 -J-Xss10m.

成功编译了 javac

但是虽然这足以编译和 运行 程序(运行ning 不需要大的堆栈大小),但此源代码仍然会在 IDE 中引起问题或奇怪的行为,而这些问题不是配置为使用更大的堆栈大小处理此源代码。递归解析和处理源代码,太常见了。

此外,编译代码的大小接近方法大小限制,因此没有太多空间容纳更大的列表。所以我只能赞成 建议转向使用资源来处理这种大小的常量列表。