Does Java G1 garbage collector respect MaxHeapFreeRatio parameter? - java

Does the Java G1 garbage collector (as implemented in Open JDK) respect the -XX:MaxHeapFreeRatio=n JVM parameter?
Does it respect it in Java 8?
I found JEP 346: Promptly Return Unused Committed Memory from G1
delivered in Java 12, but it's not clear to me what was the state before it.

A non-authoritative answer that I found is based on https://bugs.openjdk.java.net/browse/JDK-8078039?focusedCommentId=13632717&page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel#comment-13632717
Most notably, some GCs support it, some do not. This RFE doesn't say
which GC is used, so I assume we are talking about the default GC
which supports MaxHeapFreeRatio. G1 also supports this option.
To shrink the heap (and release memory) a full GC is required. It the
application doesn't trigger a full GC manually, it may take a while
before one is triggered by the JVM.
So the answer would be (for Java 8): yes... but no.
yes, it supports the option
but only when full GC happens, which may be never
(I remain curious whether there is a more authoritative source and what's the current state, in more modern JVMs)

I do not know a more authoritative answer than the source code and yes, you are correct in your answer - the release of the memory will happen only after a Full GC (at least before that JEP).
For java-8:
That argument does matter, look here for example.
That code is not very complicated to understand, and here is the actual shrink that happens.
For a much more extensive answer (regarding java-11, but still qualifies to java-8), read this.
The bottom-line is that - that flag does matter, but how exactly is implementation dependent. There is no simple answer to your question.

Related

How to monitor memory after major garbage collection via JMX or code

Many monitoring tools, like the otherwise phantastic JavaMelody, just monitor the current memory usage. If you want to check for memory leaks or impending out of memory situations, this is not particularily helpful, if you have an application that generates loads of garbage which gets collected immediately. Not perfect, but IMHO much more interesting, would it be to monitor the memory usage immediately after a major garbage collection. If that's high, a crash is looming over you.
So: can you find out the memory usage immediately after the last major garbage collection - either from Java code or via JMX? I know there are some tools like VisualVM which do this (which is no option for production use), and it can be written in the garbage collection log, but I'm looking for a more straightforward solution than parsing the garbage collection logfile. :-) To be clear: I'm looking for something that can easily be used in any application in production, not any expensive tool for debugging.
In case that matters: JDK 7 with -XX:+UseConcMarkSweepGC , but I am interested in general answers, too.
Information about memory available right after gc (youg or old) is available via JMX.
Garbage collector MBean has attribute LastGcInfo which is composite data object including information about memory pool sizes before and after GC.
In addition, starting with Java 7 JMX notification subscription could be used to receive GC events without polling.
You can find example of code working with GC MBean here.
Probably 'Dynatrace' is an option... it's a very powerful monitoring tool (not only for memory).
http://www.dynatrace.com/en/index.html
A very crude way would be to monitor the minima of Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory() for some time. At least that would not require you to know intimate details about memory pools, as monitoring LastGcInfo in Alexey Ragozin's answer does. This might require you to get notifications about garbage collections.

How to add a garbage collector of an older version to a JRE of newer version

I was asked a question as below in a recent interview.
How to add a garbage collector of an older version to a JRE of newer version
Couldn't get a proper answer from internet. Can anyone explain this to me?
Thanks in advance
You can't. The garbage collector is part of the JVM, and can't just be moved around. If you have the source code for both you could consider trying to patch the collector back in - but it would probably be a very large task, and I'd be incredibly wary of the reliability of the result... other bits of the JVM may well depend on assumptions about the garbage collectors available.
Assuming these are different versions of the same VM, I'd expect a garbage collector only to be retired if the available ones were superior in most ways, so I don't expect you'd get significant benefit anyway - at least outside some very specialized situations.
(I'm glad that this was just an interview question rather than a real life situation. Although as Jigar says, maybe they weren't actually thinking of adding a particular collector to a VM that didn't really support it. Either way, it seems like a pretty bizarre interview question.)
May be interviewer was looking for vm flags that you can pass to activate particular garbage collector for example with jre 7 you can still say -XX:-UseSerialGC to make it use serial gc

Is G1GC still not officially production ready?

I wonder what the official status of the "garbage first" (G1) collector in the JDK 7 release is. I would like to use G1 as a low pause gc alternative to CMS, but only if I can really trust on its robustness.
Before JDK 7 was out, G1 was advertised as the shiny new gc going to replace the CMS collector and even to be the default gc in JDK 7. However, now with Oracle JDK 7u1, G1 is not the default gc on any machine I have tried.
Even though one does not need to specify -XX:+UnlockExperimentalVMOptions anymore when using -XX:+UseG1GC in JDK 7, it's a JVM feature that's officially completely undocumented:
Java 7 (JDK 7) garbage collection and documentation on G1
The only official document I could find that mentions G1 is seriously outdated and was written long before JDK 7 was out:
http://www.oracle.com/technetwork/java/javase/tech/g1-intro-jsp-135488.html
For example, the official "Java HotSpot VM Options" documentation ( http://www.oracle.com/technetwork/java/javase/tech/vmoptions-jsp-140102.html ) documents how to enable and tune the other collectors but does not even mention the existence of G1. As if it didn't exist!
This is quite confusing and I wonder what the real status of the G1 and what its future is. Is it really stable yet? Have the remaining issues (like leaks, spurious crashes and missing instrumentation support) been resolved? And if so, why does Oracle treat the G1GC as an undocumented (embarrassing?) secret? Is G1 perhaps a failed project that's now silently discontinued? Or do I need to pay for documentation and support? Or is it just still beta? Can someone enlighten me on what's going on here?
The place to ask this question is on the hotspot-gc-dev mailing list.
If you look through the archives you'll find that there is a lot of work being done. A lot of the mail appears to be commits and review requests/comments so they're busy working on it.
I haven't found any official news announcements, but that is how Oracle works. You might be able to ask on that mailing list how they think they're going, if you're happy with an unofficial and non-binding comment from one of the devs.
EDIT: #scravy sent an email to the mailing list, this is the response received:
I don't think there is a simple answer to this question, though
probably not. G1's initial focus was to provide reasonable pauses
for extremely large heaps. Which means today it might not be the
best choice for everyone. We think the technology has 'a lot of
legs' though, meaning that with adaptation, it can address many
different kinds of garbage collection demands. So one day, it
might effectively be the default collector, but it is too soon to
know for sure.
Considering that GC behavior changes can be very disruptive to
existing deployments, we are reluctant to make shifts like this
even in major releases without considerable advanced notice. So in current releases, if you
don't specify a collector, we attempt to make some simple
automated choices, but I doubt we'd make radical changes to that
behavior in the near term.
For the bigger question regarding is G1 supported, the current
answer is no. But keep in mind that the support commitment that
Oracle makes to its paid customers for supported products is
fairly significant, and there is much more to it than just meeting
the functionality and reliability requirements.
We continue to encourage everyone to test and evaluate G1, and of
course, deliver feedback to us, as we continue significant
development on G1.
-John
EDIT: According to this link on Oracle's site it looks like G1GC is now fully supported.
We are already using G1GC, from almost a year and half. Its doing great in our mission critical transaction processing system, and It proved to be a great support w.r.t high throughput, low pause, concurrency, multi-threading and optimized heavy memory management.
We are using following JVM settings:
-server -d64 -Xms512m -Xmx3072m -XX:+HeapDumpOnOutOfMemoryError -XX:+UseG1GC
-XX:+UnlockExperimentalVMOptions -XX:+AggressiveOpts -XX:+DoEscapeAnalysis
-XX:MaxGCPauseMillis=400 -XX:GCPauseIntervalMillis=8000
-XX:+UseCompressedOops -XX:NewRatio=50
According to this: http://www.oracle.com/technetwork/java/javase/tech/g1-intro-jsp-135488.html,
G1 development is now focused primarily on resolving any remaining
reliability issues and improving performance
Also,
In terms of GC pause times, G1 is sometimes better and sometimes worse
than CMS. Work is ongoing to make G1 consistently as good as, if not
better than, CMS.
So G1 is supposedly going to replace CMS when the official JDK SE 7 is out.
AFAIK, G1 is not secret -- it's open for experimental use long enough -- at least year or two. Every JavaOne comes with some lection about how good G1 will be :)
From unofficial sources: it's one of current focuses for java engeneers, to make G1 production ready at last. They just was not ready to open it for JDK 7. Just keep waiting :)
It looks like the page linked in the question has been updated:
The Garbage-First (G1) garbage collector is fully supported in Oracle
JDK 7 update 4 and later releases.
(Note, however, that for embedded platforms like ARM, it is not yet supported at all in 7u4.)
G1 GC is production ready since Java 7 update 4 version launch.
From oracle article (under The G1 Garbage Collector), you can find real use cases for G1 GC.
Applications running today with either the CMS or the ParallelOldGC garbage collector would benefit switching to G1 if the application has one or more of the following traits.
Full GC durations are too long or too frequent.
The rate of object allocation rate or promotion varies significantly.
Undesired long garbage collection or compaction pauses (longer than 0.5 to 1 second)
Have a look at related question for more details about G1GC and key parameters to be fine tuned:
Java 7 (JDK 7) garbage collection and documentation on G1
Regarding your other queries:
Is it really stable yet? Have the remaining issues (like leaks, spurious crashes and missing instrumentation support) been resolved? And if so, why does Oracle treat the G1GC as an undocumented (embarrassing?) secret? Is G1 perhaps a failed project that's now silently discontinued? Or do I need to pay for documentation and support? Or is it just still beta? Can someone enlighten me on what's going on here?
G1GC is stable.
I have not found any leaks in this algorithm.
Oracle did not keep it undocumented. You can find more info about G1GC here and here
G1 is not a failed project and G1GC is going to be default GC algorithm in newer versions of java (java 9)
You don't need to pay for support. It's not beta.

JVM with no garbage collection

I've read in many threads that it is impossible to turn off garbage collection on Sun's JVM. However, for the purpose of our research project we need this feature. Can anybody recommend a JVM implementation which does not have garbage collection or which allows turning it off? Thank you.
I wanted to find a fast way to keep all objects in memory for a simple initial proof of concept.
The simple way to do this is to run the JVM with a heap that is so large that the GC never needs to run. Set the -Xmx and -Xms options to a large value, and turn on GC logging to confirm that the GC doesn't run for the duration of your test.
This will be quicker and more straightforward than modifying the JVM.
(In hindsight, this may not work. I vaguely recall seeing evidence that implied that the JVM does not always respect the -Xms setting, especially if it was really big. Still, this approach is worth trying before trying some much more difficult approach ... like modifying the JVM.)
Also, this whole thing strikes me as unnecessary (even counter-productive) for what you are actually trying to achieve. The GC won't throw away objects unless they are garbage. And if they are garbage, you won't be able to use them. And the performance of a system with GC disabled / negated is not going to indicative of how a real application will perform.
UPDATE - From Java 11 onwards, you have the much simpler option of using the Epsilon (no-op) garbage collector; see
JEP 318: Epsilon: A No-Op Garbage Collector (Experimental)
You add the following options when you launch the JVM:
-XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC
When the heap is filled, no attempt is made to collect garbage. Instead, the Epsilon GC terminates the JVM.
Depending on your needs this could perhaps work:
Using the -Xbootclasspath option you may specify your own implementation of API classes. You could then for instance override the implementation of Object, and add to the constructor, a globalList.add(this) to prevent the objects from being garbage collected. It's a hack for sure, but for simple case-study it's perhaps sufficient.
Another option is to take an open source jvm and comment out the parts that initiate garbage collection. I would guess it is not that complicated.
Sun's JVM has no such option. AFAIK, no other JVM has this option either.
You did not state what it is that you are exactly trying to achieve but you have one of two options: either use a profiler and see exactly what the GC is doing, that way you can take its effects into consideration. The other is to compile one of the JVMs from source, and disable GC from there.
You can only turn off the GC if its not actually needed (otherwise your application would run out of memory) and if you didn't need to GC, it shouldn't run anyway.
The simplest option would be to not discard any objects, this will avoid GC being performed (And set the max memory very high so you don't run out).
You may find that you get GCs on startup and you may consider a no-GC when running acceptable.
the question is old but for those who might be interested, there is a proposal to
Develop a GC that only handles memory allocation, but does not implement any actual memory reclamation mechanism. Once available Java heap is exhausted, perform the orderly JVM shutdown.
JEP draft: Epsilon GC: The Arbitrarily Low Overhead Garbage (Non-)Collector
Maybe you could try making your VM's available memory sufficient for GC never to be run.
My (allbeit limited) experience leads me to suggest that the VM is, by default, extremely lazy and extremely reluctant to run GC.
giving -Xmx 16384M (or some such) and making sure that your research subject stays well below that limit, might give you the environment you wish to obtain, allthough even then it will obviously not be guaranteed.
There actually exists a dirty hack to temporarily pause GC. First create a dummy array in Java. Then, in JNI, use GetPrimitiveArrayCritical function to get hold of the pointer to the array. The Sun JVM will disable GC to ensure that the array is never moved and the pointer stays valid. To re-enable GC, you can call the ReleasePrimitiveArrayCritical function on the pointer. But this is very implementation specific since other VM impl may pin the object instead of disabling GC entirely. (Tested to work on Oracle Jdk 7 & 8)
Take a look at Oracle's JRockit JVM. I've seen very good near-deterministic performance on Intel hardware with this JVM and you can prod and poke the runtime using the Mission Control utility to see how well it's performing.
Though you can't turn GC off completely, I believe that you can use the -Xnoclassgc option to disable the collection of classes. The GC can be tuned to minimize latency at the expense of leaving memory consumption to grow. You may need a license to drop the latency as low as you need if you're going this route.
There is also a Realtime version of the JRockit JVM available but I don't think that there is a free-to-developers version of this available.
Can you get an open source JVM and disable its GC, for example Sun's Hotspot?
If there was no Garbage Collection what would you expect to be the semantics of code like this?
public myClass {
public void aMethod() {
String text = new String("xyz");
}
}
In the absence of GC any item newed and with a stack scoped reference could never be reclaimed. Even if your own classes could decide not to use local variables like this, or to use only primitive types I don't see how you would safely use any standard Java library.
I'd be interested to hear more about your usage scenario.
If I had this problem I would get IBM's Jikes Research Virtual Machine because:
The run-time system is written in Java itself (with special extensions)
The whole thing was designed as a research vehicle and is relatively easy to tweak.
You can't turn off GC forever, because Java programs do allocate and eventually you'll run out of memory, but it's quite possible that you can delay GC for the duration of your experiment by telling the JVM not to start collecting until the heap gets really big. (That trick might work on other JVMs as well, but I wouldn't know where to find the knobs to start twirling.)

Why is memory management so visible in Java VM?

I'm playing around with writing some simple Spring-based web apps and deploying them to Tomcat. Almost immediately, I run into the need to customize the Tomcat's JVM settings with -XX:MaxPermSize (and -Xmx and -Xms); without this, the server easily runs out of PermGen space.
Why is this such an issue for Java VMs compared to other garbage collected languages? Comparing counts of "tune X memory usage" for X in Java, Ruby, Perl and Python, shows that Java has easily an order of magnitude more hits in Google than the other languages combined.
I'd also be interested in references to technical papers/blog-posts/etc explaining design choices behind JVM GC implementations, across different JVMs or compared to other interpreted language VMs (e.g. comparing Sun or IBM JVM to Parrot). Are there technical reasons why JVM users still have to deal with non-auto-tuning heap/permgen sizes?
The title of your question is misleading (not on purpose, I know): PermSize issues (and there are a lot of them, I was one of the first one to diagnose a Tomcat/Sun PermGen issue years ago, when there wasn't any knowledge on the issue yet) are not a Java specifity but a Sun VM specifity.
If you use a VM that doesn't use permanent generation (like, say, an IBM VM if I'm not mistaken) you cannot have permgen issues.
So it's is not a "Java" problem, but a Sun VM implementation problem.
Java gives you a bit more control about memory -- strike one for people wanting to apply that control there, vs Ruby, Perl, and Python, which give you less control on that. Java's typical implementation is also very memory hungry (because it has a more advanced garbage collection approach) wrt the typical implementations of the dynamic languages... but if you look at JRuby or Jython you'll find it's not a language issue (when these different languages use the same underlying VM, memory issues are pretty much equalized). I don't know of a widespread "Perl on JVM" implementation, but if there's one I'm willing to bet it wouldn't be measurably different in terms of footprint from JRuby or Jython!
Python/Perl/Ruby allocate their memory with malloc() or an optimization thereof. The limit to the heap space is determined by the operating system rather than the VM, so there's no need for options like -Xmxn. Also, the garbage collection is simpler, based mostly on reference counting. So there's a lot less to fine-tune.
Furthermore, dynamic languages tend to be implemented with bytecode interpreters rather than JIT compilers, so they aren't used for performance-critical code anyway.
The essence of #WizardOfOdds and #Alex-Martelli's answers appear to be correct: Java has an advanced set of GC options, and sometimes you need to tune them. However, I'm still not entirely clear on why you might design a JVM with or without a permanent generation. I have found a bunch of useful links about garbage collection in Java, though not necessarily in comparison to other languages with GC. Briefly:
The Sun GC evolves very slowly due to the fact that it is deployed everywhere and people may rely on quirks in its implementation.
Sun has detailed white papers on GC design and options, such as Tuning Garbage Collection with the 5.0 Java[tm] Virtual Machine.
There is a new GC in the wings, called the G1 GC. Alex Miller has a good summary of relevant blog posts and a link to the technical paper. But it still has a permanent generation (and doesn't necessarily do a great job with it).
Jon Masamitsu has (had?) an interesting blog at Sun various details of garbage collection.
Happy to update this answer with more details if anyone has them.
This is because Tomcat is running in the Java Virtual Machine, while other languages are either compiled or interpreted and run against your actual machine. When you set -Xmx and -Xms you are saying that you want to JVM to run like a computer with am amount of ram somewhere in the set range.
I think the reason so many people run in to this is that the default values are relatively low and people end up hitting the default ceiling pretty quickly (instead of waiting until you run out of actual ram as you would with other languages).

Categories