-2

My java version is as below.

java version "1.8.0_121"
Java(TM) SE Runtime Environment (build 1.8.0_121-b13)
Java HotSpot(TM) 64-Bit Server VM (build 25.121-b13, mixed mode)

And my program is very simple. The code is as below.

import java.util.concurrent.ThreadLocalRandom;

public class Test {

    static class DummyObj {
        public String t1;
        public Integer t2;
        public Long t3;
        public Double t4;

        public DummyObj() {
            int i = ThreadLocalRandom.current().nextInt(10000);
            t1 = "t1t1t1" + i;
            t2 = 222 + i;
            t3 = 3333L + i;
            t4 = 44444.0 + i;
        }
    }

    void f1() {
        for (int i=0; i<100; ++i) {
            DummyObj t0 = new DummyObj();
            if (8 == ThreadLocalRandom.current().nextLong(1000000))
                System.out.println(t0.t3);
        }
    }

    public static void main(String... arg) {
        Test t0 = new Test();
        while (true) {
            t0.f1();
            try {
                Thread.sleep(2L);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
};

I run below command to run this program

javac test.java
java -Xmx8m test

The program always collapse with OutOfMemoryError.

Does anyone know why the gc cannot free the memory?

Beyond that I am making this experiment in order to understand how the Java Garbage Collector works (so this is not some sort of "production code" - it is meant to show the GC "doing its job").

GhostCat
  • 137,827
  • 25
  • 176
  • 248
Sean Lin
  • 371
  • 3
  • 8
  • 3
    For starters, `-Xmx8m` limits heap space to 8 ***mega***bytes. That is a ***tiny*** amount of memory. Try `-Xmx512m` instead. – Jim Garrison Jan 16 '18 at 08:36
  • 1
    Take care of Java naming convention. Class names should start with uppercase letter – Jens Jan 16 '18 at 08:37
  • Even for [mcve] - naming matters. Using identifiers that are *human readable*. *Minimal* doesn't mean that you should use names that have no meaning whatsoever. – GhostCat Jan 16 '18 at 08:37
  • This is Stackoverflow NOT Codegolf. These people are not code golfers. https://codegolf.stackexchange.com/ – hellzone Jan 16 '18 at 08:40

1 Answers1

2

First of all, you are running that JVM with 8 MB of memory. That is like "nothing" for a Java application.

And then you are creating new objects on high rate. Yes there is some sleeping, but still your code is simply creating garbage all the time. If the only purpose of your code is to create garbage - how do you expect any garbage collector to keep up with that?

That is the whole point: garbage collection isn't magic. It still needs time to happen. And when you combine

  • super few memory to start with
  • code doing nothing else but creating garbage and sleeping

your application will sooner or later run out of memory.

As you state that you "want to learn" how GC works by testing ... the answer to that question is even shorter: you can't. Garbage collection is advanced, complex topic. You absolutely can't "learn" how it works by writing small test cases that do this or that. Modern day Java garbage collectors do zillions of different things. Keep in mind: this technology had 20+ years of research going into it. The effects that you might be able to observe through testing will not give you enough information to learn anything. You are like a person trying to understand all things in a huge, huge room - whilst being on the outside, trying to look through the key hole!

You will have to bite the bullet here - meaning: you will have to study documentation and tutorials. Start here or directly on SO, on this question that has many in-depth answers).

GhostCat
  • 137,827
  • 25
  • 176
  • 248
  • Thanks @GhostCat . Let me try larger memory. I wrote this program just because I wanted to test how gc works. If not creating garbage, how can I do the testing? – Sean Lin Jan 16 '18 at 08:50
  • 1
    @SeanLin I updated my answer. Basically the point is: you can't "learn" GC workings by "testing" it. You absolutely have to do a **lot** of studying first. – GhostCat Jan 16 '18 at 09:26
  • I tried to increase the memory to 32m, and no out of memory any more. – Sean Lin Jan 16 '18 at 10:54
  • @SeanLin I guess: as soon as you remove that sleep statement, you would see them again ;-) – GhostCat Jan 16 '18 at 11:26
  • *"It still needs time to happen. And when you combine [...] code doing nothing else but creating garbage and sleeping [...] your application will sooner or later run out of memory."* This is outright false. A pausing collector will happily slow down the application by doing the work is necessary to keep up with the allocations. (modulo the overhead limit exceeded heuristic, but that can be turned off). You only receive an OOM when the collector cannot satisfy an allocation request after all efforts including some heroics have failed or when it is obvious it cannot be satisfied. – the8472 Jan 16 '18 at 21:46
  • @the8472 When you write code that uses 100% of the CPU to create *new* garbage, then running out of memory is almost inevitable.That is the whole point here. – GhostCat Jan 17 '18 at 09:23
  • @GhostCat not at all, if you create new *garbage* then you will never run out of memory because garbage by definition is eligible for collection. You'll just burn a lot of CPU time on getting it collected. Weak generational hypothesis and all. You will run out of memory if you implement what amounts to a leak, which creates live data, i.e. non-garbage. – the8472 Jan 17 '18 at 21:14
  • @the8472 I get your point now. I will reword my answer ... but probably not today ... – GhostCat Jan 18 '18 at 13:54