Two questions about the CMS collector:
Will ParNew run concurrently with a CMS old gen collection.
In the GC log, I do not see the old gen usage after a CMS collection. How can I check how much space is collected in the old gen and how much still remains.
Thanks,
Yes - ParNew will run whilst CMS is performing one of its concurrent phases. This can lead to GC log corruption as the JVM's logging is not thread-safe with respect to the GC threads.
CMS performs a parallel sweep. While this is running, a ParNew can cause objects to be promoted to old gen. The question "how much memory was collected by CMS?" is therefore neither very useful or entirely meaningful.
Related
I would like to understand why the GC gets triggered even though I have plenty of heap left unused.. I have allocated 1.7 GB of RAM. I still see 10% of GC CPU usage often.
I use this - -XX:+UseG1GC with Java 17
JVMs will always have some gc threads running (unless you use Epsilon GC which perform no gc, I do not recommend using this unless you know why you need it), because the JVM manages memory for you.
Heap in G1 is divided two spaces: young and old. All objects are created in young space. When the young space fills (it always do eventually, unless you are developing zero garbage), it will trigger some gc cleaning unreferenced objects from the young and promoting some objects which are still referenced to old.
Those spikes in the right screenshot will correspond to young collection events (where unreferenced objects get cleaned). Young space is always much more small than the old space. So it fills frequently. That is why you see those spikes regarding there is much more memory free.
DISCLAIMER This is a really very high level explanation of memory management in the JVM. Some important concepts have been not mentioned.
You can read more about g1 gc collector here
Also take a look at jstat tool which will help you understand what is happening in your heap.
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).
how can I make gc clear the tenured space?
we running app using docker image
There are two potential issues here.
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.
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.
According to the Java Platform, Standard Edition HotSpot Virtual Machine Garbage Collection Tuning Guide section titled "Generations"
When the young generation fills up, it causes a minor collection in which only the young generation is collected
and:
Eventually, the tenured generation will fill up and must be collected, resulting in a major collection, in which the entire heap is collected.
So if the application has finished the allocation phase, and
throughout the execution of the application, the young and tenured generations are never filled (at all, at any stage), then gc will not occur even once?
If it will occur, what is the reason? Because such seems contrary to the linked documentation.
So if the application finished the allocation phase, and throughout the execution of the application, the young and tenured generations are not filled up (at all, in any stage), the gc will not occur even once ?
Yes. If the young and tenured generations are not filled (at any stage) then the gc may not occur (even once). It's up to the JVM runtime to manage memory, and that includes deciding when (or if) garbage collection occurs.
List of Garbage Collectors:
Serial GC
Parallel GC
Parallel Old GC
Conc Mark Sweep GC
G1 GC
I know that the Conc Mark Sweep GC supports cleaning up PermGen when you enable the ClassUnloading JVM option. Do other Garbage Collectors support cleaning up PermGen?
Reason: We use Spring, Hibernate, and Groovy that create a lot of Proxies and Perm Gen gets big.
Edit:
Should have mentioned that I am using Java 7. I'm aware of Java 8 removing Perm Gen and hopefully will upgrade sometime in the future. In the meantime, my question is regarding if the other garbage collectors support cleaning up PermGen other than Conc Mark Sweep.
Serial GC
Parallel GC (Believe -server uses this by default and confirmed that it cleans up perm gen)
Parallel Old GC
Conc Mark Sweep GC (Can clean perm gen using JVM flag)
G1 GC
All algorithms are cleaning PermGen, but
not every GC cycle include PermGen cleaning
CMS can clean PermGen concurrently, G1 have been requiring stop-the-world Full GC to unload classes (clean PermGen) until Java 8u40
Java 8 have metaspace instead of PermGen, but it needs to be garbage collected too (otherwise you'll get OOME in metaspace)
I have been fighting OOME in PermGen quite a lot when I was actively used ClassLoaders to simulate multiple JVM in single process for test purposes. My conclusion: PermGen GC is just not very reliable. One run it works as expected, other it throws OOEM.
The problem with perm gen is that it was not supposed to be dynamic, it was supposed to be static data, like classes and constants. But what we developers are doing with java are things like creating classes on the fly, redefining classes, etc which required a more dynamic usage of that space and that's why in the metaspace case, it has to be.
The biggest issues with perm gen and, going back to your question that IMO doesn't go away with metaspace is the creation and destruction of the class loaders as it is too easy to leak class metadata in ThreadLocals and other libraries loaded by other classloaders and that will leave live objects that cannot be reclaimed by any of the collectors that you use.
Nowadays all production garbage collectors clean up the metaspace, but, they are not bound to clean it with the same frequency as other memory regions
Have sort question - is it true that all GC in JDK 7 (other than G1) always use stop-the-world for young generation collection?
thanks
For OpenJDK, JRockit, IBM JVM, and Sun/Oracle JDK, the young collection is always stop the world for every available collector.
The only JVM I know of which does not have a stop the world collector is Azul's Zing. (Not free)
While OpenJDK/Hotspot has CMS this is mostly concurrent. There is still stop the world portions and in some cases CMS will fall back to a Full GC which is stop-the-world.
AFAIK, It is hard to find real world examples where G1 is faster in terms of pause time than CMS, however it is improving all the time.
Do your GC logs speak to you
All (almost) Java garbage collectors has some sort of a Stop-the-world phase where all the Java threads (not native threads) are suspended waiting for exclusive system operations to complete. This state is sometimes referred to as a safepoint.
The modern garbage collectors are concurrently running together with the applications threads, which means that the garbage collector perform its work at the same time as the application threads are running. During the garbage collector process there are phases where exclusive access memory is needed, in that phase the application Java threads goes into the safepoint state.
One alternative to get rid of the stop-the-world garbage collections is to go for the Zing JVM with the C4 collector from Azul systems. The implementation has a low pause approach with no stop-the-world collections at all. Instead it is using a concurrent compacting approach with no stop-the-world phase.
No it is not true. Java 7 also supports the older Concurrent Mark Sweep (CMS) collector. CMS is a low pause collector, just like G1.
UPDATE
Apparently CMS is only for the tenured generation ... according to the blog posting that you found at http://blogs.oracle.com/jonthecollector/entry/our_collectors
So that means that your proposition is in fact true.
One could argue that all of the low-pause collectors:
- need to stop the mutator threads to do some phases of their work, and
- may fall back to a Full GC using the mark/sweep collector when they can't keep up.
However, there is a qualitive difference between "mostly concurrent" collectors like G1 and CMS, and other collectors that suspend non-GC threads for the entire duration of the collection process. That is what is normally meant by a "stop the world" strategy.