Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Force JVM to free memory

I improved my code to get a better result from the garbage collector.

Now when i call System.gc() it does free all memory. But when I watch the memory usage without calling System.gc() the application does reserve and use more and more memory.

Does it mean my improvements are working and I got all my references right and I can ignore how the JVM does free memory by itself. Or are there another problems in my code that are the reasons why the JVM does reserve more memory without running the garbage collector.

like image 542
Dennis Avatar asked Jan 19 '19 13:01

Dennis


People also ask

How do I free up JVM memory?

When a Java program needs memory, it requests this memory from the JVM. If there is no memory left, then the JVM will attempt to free some memory by using the garbage collector. The garbage collector will try to release memory that is no longer required to run the program back to the JVM.

Does the JVM ever release memory?

The JVM does release back memory under some circumstances, but (for performance reasons) this does not happen whenever some memory is garbage collected. It also depends on the JVM, OS, garbage collector etc. You can watch the memory consumption of your app with JConsole, VisualVM or another profiler.

How can I be free in Java?

freeMemory() method returns the amount of free memory in the Java Virtual Machine. Calling the gc method may result in increasing the value returned by freeMemory.


4 Answers

Depends which GC your JVM is using. If it is JDK9 then its probably G1 which is 'greedy' when it comes to memory consumption, so depending on the way in which you are checking memory utilized, it can appear as if it is taking up a lot of memory (where as this is reserving it and using/freeing dynamically/on demand.

You can use

https://docs.oracle.com/javase/8/docs/technotes/tools/unix/jstat.html

to check memory consumption.

And as for GC and memory consumption analysis check out following: High memory usage issues with G1 Garbage collector + https://www.javacodegeeks.com/2017/11/minimize-java-memory-usage-right-garbage-collector.html

like image 82
ejaksla Avatar answered Oct 23 '22 11:10

ejaksla


Unused memory is wasted memory.

Why do you want to explicitly call System.gc(). IMHO, you should never call it and leave it up to the JVM to decide when to run GC. (JVM can make better decisions than you if you are a novice. Call System.gc() only when you really know what you are doing.) It's generally a bad practice to call System.gc().

System.gc() is just a request/hint to the JVM to run GC. It in no way means that for sure GC will run.

You can have memory leaks in Java, but that's for sure not the thing to look at in your case because as you mentioned when you invoke System.gc() you can see some memory getting freed up. (So it is not the case that you are still holding the reference of unused objects which can prevent GC from cleaning up those objects.)

Why do you think it's a problem with your code? It can be the case that no further memory is required or if memory is required, you already have plenty amount of it (and speaking in layman terms, GC don't frees up memory as there is still a lot for the program to run - so why should GC bother clearing the memory?).

like image 27
Lavish Kothari Avatar answered Oct 23 '22 11:10

Lavish Kothari


There is no way to force JVM to free up the memory, System.gc() is just a hint. It's up to GC to manage the memory (do note there are various types of memory e.g. heap, meta space, off-heap). Each GC algorithm has multiple configuration parameters that you can tweak but neither will give you an option to free up the memory on demand.

JVM reserves memory on startup and requests additional memory from the OS until it reaches whatever limits are configured. It does it in chunk increments, requesting MBs or more memory at a time, because requesting memory from the OS byte by byte would be very inefficient.

like image 44
Karol Dowbecki Avatar answered Oct 23 '22 13:10

Karol Dowbecki


There is of course a possibility that you have a memory leak, meaning that your program keeps allocating memory without ever freeing it. (For example, in an ever-growing list or map.) You will need a memory profiler in order to make sure you are not suffering from such a situation.

Other than that, I would not worry if the virtual machine appears to keep allocating memory without freeing it. That's how modern VMs work, especially in "client" mode: for as long as there is plenty of free memory, they will not waste time with garbage collection. If the limit of memory is approached, that's when the garbage collector will kick-in. (The "client" vs. "server" mode is a JVM argument, you can experiment with it if you want, more info here: Real differences between "java -server" and "java -client"?)

Other than that, what you can do is:

a) make sure that your mechanism of performing a full GC is actually performing a full GC. The best mechanism that I know of (which is not guaranteed to work, but it seems to work as far as I can tell) is to allocate an object referenced only via a soft reference, and then keep calling GC until the soft reference becomes null.

b) on a debug run, (say, if assertions are enabled,) keep triggering a full GC on a separate thread every few seconds. Then, if you look at the memory consumed by the VM, it should remain roughly constant. If not, you have a memory leak.

like image 20
Mike Nakis Avatar answered Oct 23 '22 12:10

Mike Nakis