1

I'm trying to define a global constant ImmutableList that is too large for the default stack size limit, and I'm wondering if there's a way to get around it other than passing an aggressive Xss32M flag to java.

Here's the code snippet:

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 */
}

There are roughly 2000 lines like the above, and I guess the reason why the class blows up is that each element is an Object (although very lean).

Is there a way such that I can define student_list in Java such that it won't cause the StackOverflow error like I currently observe?

Zz'Rot
  • 824
  • 1
  • 7
  • 24
  • 5
    Read it from a file. – pvg Nov 07 '17 at 18:13
  • You should not be hardcoding that much into a class. That should come from a file. – Louis Wasserman Nov 07 '17 at 18:17
  • @EricWang: when you chain method invocations, each invocation happens *after* the previous returned. The code itself does *not* produce stack overflows. It’s the *compiler* which fails with a `StackOverflowError` while processing the source code. – Holger Nov 08 '17 at 13:57

2 Answers2

3

StackOverflow error that you are observing is due to call chaining in the builder pattern. You can avoid it by adding a variable in a static initializer:

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();
    }
}

Obviously, this is not very elegant, but it fixes Stack Overflow error.

You can improve on this approach by reading the data from a file, which could be embedded as a resource into your Java program.

This Q&A explains how to read from an embedded resource. Since your program owns the content of the resource, you could populate the builder with a small amount of code and virtually no error checking.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
2

To answer your original question, you can pass JVM options to javac using the -J option. E.g. I took your code template, created a chain of 3600 invocations and successfully compiled it with javac using -J-Xss10m.

But while this is sufficient to compile and run the program (running does not need a large stack size), this source code still causes problems or weird behavior within IDEs which are not configured to process this source code using a larger stack size. Parsing and processing source code recursively, is too common.

Also, the compiled code has a size close to the method size limit, so there’s not much room for larger lists. So I can only second this answer’s recommendation to turn to using resources for constant lists of this size.

Holger
  • 285,553
  • 42
  • 434
  • 765