0

The code below 100% throws java.lang.OutOfMemoryError

Set<Integer> set = new HashSet<>();
    new Random().ints(10_000_000,
            Integer.MIN_VALUE,
            Integer.MAX_VALUE)
            .forEach(
                    v -> {
                        if(set.contains(v)){
                            System.out.println(v);
                        }else{
                            set.add(v);
                        }
                    }
            );

AFAIK it's because lambda capture Integer with context? Could anybody explain what exactly happens here?

J.J. Beam
  • 2,612
  • 2
  • 26
  • 55
  • What is your java version? I have openjdk version "11.0.12" 2021-07-20 OpenJDK Runtime Environment Homebrew (build 11.0.12+0) OpenJDK 64-Bit Server VM Homebrew (build 11.0.12+0, mixed mode). When I run this code with `-Xmx128m` heap never goes higher than 90mb – geobreze Nov 17 '21 at 17:34
  • sorry, I edit the code sample, try please – J.J. Beam Nov 17 '21 at 19:35

1 Answers1

1

In your code you have Set which is accessible from main method. Local stack is a GC root, so it could not be collected by GC.

So, you're adding elements to the set which can't be collected. And set requires extra memory to store elements.

On my PC it's required about 600 MB of heap to run this program without OOM.

Here is heap dump of this program running on my pc.

heap dump

I've tried the same code with vanilla for loop and got the same results.

So you just need to add more memory for your application. For example -Xmx1g will set your heap size to 1 gigabyte.

geobreze
  • 2,274
  • 1
  • 10
  • 15
  • actually I started the code from unit test, is it the same as from main method? – J.J. Beam Nov 17 '21 at 21:54
  • Yeah, when starting from unit test, your code is accessible from local stack too. You can set memory settings in configuration of your surefire plugin https://stackoverflow.com/a/7579853/4655217 – geobreze Nov 18 '21 at 10:01