Java 定义一个巨大的全局不可变列表常量的优雅方法(超出堆栈大小限制)

Java 定义一个巨大的全局不可变列表常量的优雅方法(超出堆栈大小限制),java,memory,jvm,stack-overflow,Java,Memory,Jvm,Stack Overflow,我试图定义一个对于默认堆栈大小限制来说太大的全局常量不可变列表,我想知道除了向java传递一个激进的Xss32M标志之外,是否还有其他方法可以绕过它 下面是代码片段: import com.google.common.collect.ImmutableList; import util.FixedRowDefinition; import java.util.List; public class FancyConstants { public static final List<

我试图定义一个对于默认堆栈大小限制来说太大的全局常量不可变列表,我想知道除了向
java
传递一个激进的
Xss32M
标志之外,是否还有其他方法可以绕过它

下面是代码片段:

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 */
}
import com.google.common.collect.ImmutableList;
导入util.FixedRowDefinition;
导入java.util.List;
公共类FancyConstants{
public static final List student_List=new ImmutableList.Builder()
.添加(新人物(“艾米”,12,56))
.add(新人(“汤姆”,26,79))
.........
.add(…).build()
/*更相似的定义;可能很长*/
}
大约有2000行类似于上面的代码,我想类爆炸的原因是每个元素都是一个对象(尽管非常精简)


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

您观察到的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();
    }
}
公共类FancyConstants{
公开静态最终名单学生名单;
静止的{
ImmutableList.Builder=新的ImmutableList.Builder();
建筑商。添加(新人员(“艾米”,12,56));
建筑商添加(新人员(“Tom”,26,79));
.........
/*更相似的定义;可能很长*/
生成器。添加(…);
student_list=builder.build();
}
}
显然,这不是很优雅,但它修复了堆栈溢出错误

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


解释如何从嵌入式资源中读取。由于您的程序拥有资源的内容,因此您可以使用少量代码填充
生成器
,并且几乎不进行错误检查。

您观察到的堆栈溢出错误是由于生成器模式中的调用链造成的。您可以通过在静态初始值设定项中添加变量来避免:

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();
    }
}
公共类FancyConstants{
公开静态最终名单学生名单;
静止的{
ImmutableList.Builder=新的ImmutableList.Builder();
建筑商。添加(新人员(“艾米”,12,56));
建筑商添加(新人员(“Tom”,26,79));
.........
/*更相似的定义;可能很长*/
生成器。添加(…);
student_list=builder.build();
}
}
显然,这不是很优雅,但它修复了堆栈溢出错误

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


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

要回答您最初的问题,您可以使用
-J
选项将JVM选项传递给
javac
。例如,我获取了您的代码模板,创建了3600个调用链,并使用
-J-Xss10m
使用
-javac
成功地编译了它

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


此外,编译后的代码的大小接近方法大小限制,因此没有太多空间容纳更大的列表。因此,我只能再次推荐使用资源来处理这种大小的常量列表。

要回答您最初的问题,您可以使用
-J
选项将JVM选项传递给
javac
。例如,我获取了您的代码模板,创建了3600个调用链,并使用
-J-Xss10m
使用
-javac
成功地编译了它

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


此外,编译后的代码的大小接近方法大小限制,因此没有太多空间容纳更大的列表。因此,我只能再次推荐使用资源来处理这种大小的常量列表。

从文件中读取。您不应该在类中硬编码那么多。这应该来自一个文件。@EricWang:当你链接方法调用时,每次调用都会在上一次返回后发生。代码本身不会产生堆栈溢出。是编译器在处理源代码时出现
StackOverflowerError
错误。请从文件中读取。您不应该在类中硬编码那么多。这应该来自一个文件。@EricWang:当你链接方法调用时,每次调用都会在上一次返回后发生。代码本身不会产生堆栈溢出。编译器在处理源代码时会出现
StackOverflowError
错误。