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

时间:2017-11-07 18:11:30

标签: java memory jvm stack-overflow

我正在尝试定义一个全局常量ImmutableList,它对于默认的堆栈大小限制来说太大了,我想知道是否有办法绕过它而不是将一个激进的Xss32M标志传递给{ {1}}。

以下是代码段:

java

上面大概有2000行,我猜这个类爆炸的原因是每个元素都是一个对象(虽然非常精简)。

有没有办法让我可以在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 */ } ,这样就不会像我目前观察到的那样导致student_list错误?

2 个答案:

答案 0 :(得分:3)

您正在观察的StackOverflow错误是由于构建器模式中的调用链接造成的。您可以通过在静态初始值设定项中添加变量来避免它:

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,并且几乎不会进行错误检查。

答案 1 :(得分:2)

要回答原始问题,可以使用const moment = require('moment'); let sleep = (secondsToSleep = 1) => { let sleepUntill = moment().add(secondsToSleep, 'seconds'); while(moment().isBefore(sleepUntill)) { /* block the process */ } } module.exports = sleep; 选项将JVM选项传递给javac。例如。我使用了您的代码模板,创建了一个包含3600个调用的链,并使用-J使用javac成功编译了它。

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

此外,编译后的代码的大小接近方法大小限制,因此大型列表的空间不大。所以我只能提出第二个this answer’s建议,转而使用这个大小的常量列表的资源。