6

When application is in use for few minutes then it slowly increases the Used memory value and decreases Free memory value. Application get very slow after few minutes. Why isn't it releasing the memory.

System configuration :

  • CPU : Intel(R) Xeon(R) Platinum 8175M CPU @ 2.50GHz (No. of processors : 4 / No. of cpu cores : 8)
  • RAM : 30 GB
  • OS : CentOS-7

Application configuration :

  • java version "1.8.0_171" -- build 1.8.0_171-b11
  • apache-tomcat-7.0.55

Tomcat setting

enter image description here

Free -h command

enter image description here

Top command

enter image description here

. .

Used memory value showing 12 GB occupied and Free memory value showing 600 MB free. I have performed multiple concurrent user searches and run jcmd command to generate heapdump.hprof to analyze the memory usage and observed that heapdump file size is not more than 600 MB.

Used memory is 12 GB and heapdump is of 600 MB - I don't know why memory is not releasing or getting free.

Could any one please advise any read-up on how to setup/configure to improve memory usage for a particular h/w config.

6
  • 2
    Why would the memory be released? Instead of worrying about the OS memory allocation, you should be examining why your application gets slow.
    – Kayaman
    Commented Dec 10, 2019 at 8:17
  • 1
    When application start - Used memory value is 5 to 6 GB then after each search around 600 to 800 MB are being added to "used" memory value and slowly, memory consumption increases. After sometime, total memory usage reached to 12 GB. GC should free-up memory but it's not happening. As sufficient memory not available, system get slow.
    – Santosh
    Commented Dec 10, 2019 at 8:56
  • 4
    You can't reliably know what the GC is doing based on top or free, so you're assuming things. You need to profile your application to see the real memory usage and what's making things slow.
    – Kayaman
    Commented Dec 10, 2019 at 9:26
  • 3
    Are you using any collection to store large amount of data? If yes, are you de-referencing it when that collection holding large data no longer in use? Commented Dec 10, 2019 at 10:14
  • 1
    From Java 8 onward there is no PermSpace. So you don't have to set MaxPermSize. Can you try setting Xms and Xmx for your application? Analyzing GC logs might give you an idea on application memory footprint. Commented Dec 19, 2019 at 8:29

5 Answers 5

5
+50

The issue that you are facing is Memory leak

What is it?

In computer science, a memory leak is a type of resource leak that occurs when a computer program incorrectly manages memory allocations in such a way that memory which is no longer needed is not released.

as above explained : memory which is no longer needed is not released

When it happens?

when before de-allocation of allocated heap , ref to allocated heap is disposed.while ref to heap is disposed then garbage collection won't be able address to allocated heap.on the other word , it won't be able to find orphaned allocated heap.

What does it cause in long running programs while Memory leak happens?

The program will eat RAM , CPU resources

How does it eat ?

The program constantly allocates RAM.But, does not de-allocate it.therefore, Used memory goes high and cause slow & laggy running.

How does it fixed ?

if you are using Android Studio , The intellisense feature of it, will sign Memory leak possible part of code by Yellow Color highlighting.if you hover on highlight, it will pop-out and shows you warning that why does it might cause problem.

3

As far as i can see you are only setting the permSize. Set the -Xms and -Xmx as well, so that the garbage collector kicks in when those are reached and cleans up the heap memory.

3

I don't think that there is any issue with the server, it seems the issue is with your code only.

You can use following things to improve the quality of your code if not done already,

  1. In Java8, there is a feature of "try with resources", please use that to close all your connections.

  2. Please check in your code if you have any unnecessary for loop which is just printing some loggers and running every time when the search functionality is executed.

  3. You can also run 'SonarLint' and 'SonarQube' on your code, this will help you to find out Memory leakage in your code.

  4. For testing concurrent searches, you can use jMeter.

I hope this helps.

3

Have you tried connecting a profiler to check what data types are causing this issue? A profiler like Visual VM could help you know the status of your heap, what is causing the increase, The right type of Garbage Collector to use.

3

The reduction in size could be due to, when dumping its heap, the JVM will first run a garbage collection cycle to free any unreachable objects.

If you want to get deeper on how the memory is being used, you should start by checking how the Garbage Collector is doing. First, the flags you are using don't handle the heap size

-XX:PermSize -XX:MaxPermSize are used to set size for Permanent Generation. Permanent Generation: The Permanent Generation is where class files are kept. But think of this as the class metadata, not the actual objects, those go to the heap (with some caveats)

Then set your preferences correctly for your JVM with the flags-Xms1024m -Xmx1024m and enable more logging -verbose:gc -XX:+PrintGCDetails. You will get something like this:

Heap
 def new generation   total 314560K, used 100261K [0x00000000c0000000, 0x00000000d5550000, 0x00000000d5550000)
  eden space 279616K,  35% used [0x00000000c0000000, 0x00000000c61e9370, 0x00000000d1110000)
  from space 34944K,   0% used [0x00000000d3330000, 0x00000000d3330188, 0x00000000d5550000)
  to   space 34944K,   0% used [0x00000000d1110000, 0x00000000d1110000, 0x00000000d3330000)
 tenured generation   total 699072K, used 368281K [0x00000000d5550000, 0x0000000100000000, 0x0000000100000000)
   the space 699072K,  52% used [0x00000000d5550000, 0x00000000ebcf65e0, 0x00000000ebcf6600, 0x0000000100000000)

And check the life of your objects, see how they "age" on every GC collection. These definitions below will help you to understand the lifecycle of objects in the heap better if you already don't

Heap memory The heap memory is the runtime data area from which the Java VM allocates memory for all class instances and arrays. The heap may be of a fixed or variable size. The garbage collector is an automatic memory management system that reclaims heap memory for objects,

Eden Space: The pool from which memory is initially allocated for most objects.

Survivor Space: The pool containing objects that have survived the garbage collection of the Eden space.

Tenured Generation or Old Gen: The pool containing objects that have existed for some time in the survivor space.

So if you end up with OldGen you, that would trigger a Full GC, and that may indicate you have a memory leak. This may also cause java.lang.OutOfMemoryError: GC overhead limit exceedederrors In this case, I'd inspect further the objects there to find the worm.

Otherwise, it could be that you have a high churn of short lived objects, this happens usually in ETL applications. Try to check your code to avoid instantiating objects as much as possible (check the Flyweight pattern)

And if none of these happens you could say your JVM is healthy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.