2

What conditions would prevent the JVM from running a FULL Garbage Collection when the CPU is at 5% to 8% load?

I am seeing a constant shallow GC cycle, but not able to tune the JVM to want to run FULL GC.

Where can I go to find the conditions that the JVM says "I am too busy to run".

Mick Knutson
  • 2,297
  • 3
  • 25
  • 48
  • 4
    The JVM may simply think "I'm in no *need* to run GC now." – aioobe Aug 13 '10 at 15:38
  • 2
    I think you need to flip your question around - why *should* the garbage collector run right now? Are you getting an out of memory exception? – Peter Recore Aug 13 '10 at 15:43
  • you're unlikely to find the explanation here: people have come to love the fact that in Java you can't easily control the GC. So because you can't easily force a full GC, people her will say it is a "Good Thing" [TM]. Don't question why: the Java gods decided it was like that, so it is a "Good Thing" [TM]. No if you do **REALLY WANT TO FORCE A GC**, look here: http://stackoverflow.com/questions/2178296/java-how-do-you-really-force-a-gc-using-jvmtis-forcegargabecollection (no actual answers to the OP, but the question itself contains hints and links to **REALLY** force it. – NoozNooz42 Aug 13 '10 at 17:37

3 Answers3

7

When I was studying for my SCJP certification a lot of emphasis was made on

"You can not do anything to force the GC to run at any given time, you can just give hints to it"

The whole idea of having an automatic GC is precisely not having to worry about how or when it runs to clean up free memory for you. So, there is no way to actually change when or how GC does actually run... you would have to re-implement one JVM to do what you want.

There are just so many factors involved in this, there may be other, more elegant solutions for this.

Jose Diaz
  • 5,353
  • 1
  • 31
  • 29
3

It depends entirely on the garbage collector algorithm that you're using in your particular JDK. About all you can guarantee about garbage collection is that if the JVM throws an OutOfMemoryError, the garbage collector made its best effort to collect every unreachable/weakly reachable object. Even System.gc() doesn't guarantee anything, a no-op is a completely legal implementation.

Hence in that light I don't know if your question has any weight. If you truly believe that you need to tweak the garbage collector, it would help if you posted the problems you're seeing, and the profiling data that leads to believe that poor GC performance is the problem.

Outside of this, the garbage collector should be treated like a black box. The logic behind its implementation is surprisingly complex, and there's a very good chance it knows better than you what it ought to be doing at any given time. 99 times out of 100, trying to force the garbage collector to behave in a particular way will lower performance, not increase it.

Andrzej Doyle
  • 102,507
  • 33
  • 189
  • 228
  • If the program deliberately threw an `OutOfMemoryException`, would that have an effect? Of course, at some point the same exception would also have to be caught to prevent it from halting the program... – FrustratedWithFormsDesigner Aug 13 '10 at 15:44
  • @FrustratedWithFormsDesigner: No, `OutOfMemoryException` has nothing (directly) to do with the GC. If the GC runs but you've got a memory leak (ie: objects in memory the GC won't collect because you're still referencing them), you'll get a OOME. What good would running the GC again do? It already ran! OOME is something the programmer has to deal with, not the GC. – Brian S Aug 13 '10 at 15:48
  • 1
    @FrustratedWithFormsDesigner - as Brian says, this will not achieve the desired effect. I meant solely when the *JVM* "legitimiately" throws this error due to being unable to allocate needed memory - I'll correct my answer to communicate this accordingly. – Andrzej Doyle Aug 13 '10 at 16:33
2

It's not that it's to busy to run, but it does simply not need extra memory.

thelost
  • 6,638
  • 4
  • 28
  • 44
  • Let me explain more...

    I do NOT get OOM errors. What I have is an application that is creating a LARGE amount of objects, and uses up 70% to 97% of memory before running a FULL GC. Shallow GC's do not reclaim this memory, but once a FULL GC is run, the used memory goes back to around 40%, then starts climbing again.

    SO: Why would FULL GC not run at 50% used memory as stated by -XX:CMSInitiatingOccupancyFraction=50 but only run at such a HIGH level?

    Is this because the JVM is busy?

    It is not because the objects are being used, because once t
    – Mick Knutson Aug 13 '10 at 17:20
  • Current settings: ----------------- -XX:+UseConcMarkSweepGC -XX:+CMSIncrementalMode -XX:+CMSIncrementalPacing -XX:CMSIncrementalDutyCycleMin=0 -XX:CMSIncrementalDutyCycle=10 -XX:+UseParNewGC -XX:+CMSClassUnloadingEnabled -XX:MaxGCPauseMillis=250 -XX:MaxGCMinorPauseMillis=100 -XX:SurvivorRatio=128 -XX:MaxTenuringThreshold=0 -XX:CMSInitiatingOccupancyFraction=50 -XX:NewSize=256m -XX:MaxNewSize=256m -XX:PermSize=160m -XX:MaxPermSize=160m – Mick Knutson Aug 13 '10 at 17:21
  • I am aware that I can not force the GC to run. But I want to know why the JVM thinks it should NOT run if the used memory is at 90%+ used memory? There must be some valid reason. – Mick Knutson Aug 13 '10 at 17:28
  • As a workaround, I created a simple app that checks the memory used. If it is **>50%** then issue a `System.gc()` which is just asking the JVM to run a GC, not forcing it. This keeps the used memory between 50% and 60% used memory and does not get to an Alert Threshold point. But, I do not want this long term. – Mick Knutson Aug 13 '10 at 17:36
  • @Mick Knutson: Your settings make no sense. You're specifying what seems to me to be incompatible settings with UseConcMarkSweepGC and UseParNewGC, and you're also setting [CMSIncrementalMode, which will cause CMSInitiatingOccupancyFraction to be ignored](http://forums.sun.com/thread.jspa?messageID=9536408#9536408). Perhaps [this article on the available GC choices](http://blogs.sun.com/jonthecollector/entry/our_collectors) may help clarify things for you. – Daniel Pryden Oct 28 '10 at 03:32