2

I have a java spring boot project. When the code related to multi-threading (Executor service)is executed memory is getting filled. GC is not clearing this memory. After reading GC docs, came to know that the tenured memory is not getting cleared. By monitoring the JVM by Java Profiler, I notice that this Tenured Generation never get cleared(until full, for my case).

  1. how can I make gc clear the tenured space?

we running app using docker image

saij9999
  • 282
  • 1
  • 3
  • 18
  • we added threads(50) using ExecutorService, suppose for larger files it will take a longer time to complete. Here at a certain amount of time in the middle getting out of memory heap space. tried with different GC options still not resolved – saij9999 Dec 30 '20 at 07:35
  • 1
    You don't explain why you think tenured memory is the problem. Set the `-XX:HeapDumpOnOutOfMemoryError` option when you start the JVM, and have a look at what objects are in memory when you get an OOME. – tgdavies Dec 30 '20 at 08:30
  • @tgdavies i am running the app in the docker. so i can i use Spring boot Acurator for heap dump ? will that help ? – saij9999 Dec 30 '20 at 08:58
  • 1
    I've not used actuator, but the heapdump endpoint should provide you with one, yes. – tgdavies Dec 30 '20 at 09:13

1 Answers1

1

There are two potential issues here.

  1. The garbage collector, can only release objects that are unreachable. So if the tenured objects are still reachable, they won't ever be released. This is a memory leak scenario.

  2. The JVM could be not running the old / tenured space collection because it doesn't need to. The JVM will typically only run the old space collector when it thinks it is necessary / economical to do. This is actually a good thing, because most of the easily (cheaply) collectable garbage is normally in the new space.


After reading gc docs, came to know that the tenured memory is not getting cleared.

That's probably a misreading of the documentation. The GC will collect objects in tenured space. It should happen before you start getting OOMEs.


How can I make the GC clear the tenured space?

You can call System.gc() ... which gives the JVM a hint that it would be a good thing to run the GC now. However:

  • It is only a hint. The JVM may ignore it.
  • It may or may not run an old space collection.
  • It won't "clear" the old generation. It won't necessarily even release all of the unreachable objects.
  • It is generally inefficient to call System.gc(). The JVM typically has a better idea of the most efficient time to run the GC, and which kind of GC to run.
  • Running the GC is probably not actually going to release memory for the rest of the system to use.

In short, it is probably a BAD IDEA to call System.gc(). In most cases, it doesn't achieve anything.

It certainly help if your real problem is a memory leak. If you are getting OOME's, it won't help.

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
  • for 1500 records its taking 80 percentage of CPU. is it also a memory leak ? memory is 4 GB. we added threads(50) using ExecutorService, suppose for larger files it will take a longer time to complete. Here at a certain amount of time in the middle getting out of memory heap space. tried with different GC options still not resolved – saij9999 Dec 30 '20 at 07:35
  • 1
    It is not possible to say. If you suspect there is a memory leak, you should search for Q&A's, etcetera on how to diagnose, find and fix memory leaks. (Trying different GC options is not going to cure a memory leak. The fundamental problem is in application code ... somewhere.) – Stephen C Dec 30 '20 at 07:40
  • 1
    Another possibility is that by throwing a lot of work at 50 parallel threads, you may be increasing the demand on memory to the point that the heap is too small. Distinguishing that from a real memory leak is a bit tricky. – Stephen C Dec 30 '20 at 07:50
  • thank you for the clarity. what are the possible ways to identify memory leaks in code level ? will heap dump help ? – saij9999 Dec 30 '20 at 08:55
  • Do you have a gc log? Generally speaking gc execution times are directly related to the number of objects that are live in the object graph. Shortest execution times are found when the live set is small. (both for young gen and old gen if you are running a generational gc). The amount of cpu is not coupled to the number of objects in the heap, it's coupled to what gc you are using. If you are using the parallell collector, then 80%cpu is great! Otherwise, Stephen C is spot on. But please use a gc log. – Erik Dec 30 '20 at 21:53
  • 1
    Yea. I couldn't work out what you meant by *"for 1500 records its taking 80 percentage of CPU"*. (What is "it"?) But high CPU utilization is not a clear indication of a memory leak. Also read [How to find a memory leak](https://stackoverflow.com/questions/40119) ... or Google for articles, tutorials, etc on that topic. – Stephen C Dec 30 '20 at 23:42