简体   繁体   中英

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.

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

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?).

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 eg 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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM