18

I have an application that's running on a 24x6 schedule. Currently, after running for a few days, a Full GC is performed automatically - and usually during a busy part of the day, which negatively impacts user response times.

What I'd like to do is force a Full GC - perhaps at midnight each night, during very low usage times - to prevent it from happening during the day. I've tried System.gc(), but it doesn't seem to guarantee when a Full GC will happen, or even if it will. Is there some means of doing this?

Version info:

Java(TM) SE Runtime Environment (build 1.6.0_11-b03)
Java HotSpot(TM) Server VM (build 11.0-b16, mixed mode)

Additionally -

  • Minor GCs are running, about every 10-15 seconds. But these are are not freeing up enough RAM to get the app through a full week. When a Full GC does happen, nearly 50% of the heap is freed.
  • In relation to the above, calling System.gc() doesn't seem to mean that any of the next GCs, will be of the Full form needed to free those large chucks of memory. Yes, it is enabled (or not disabled, depending on how you read the -XX option).
  • I've already played around with several of the CMS GC settings, which has helped greatly, but not solved the problem. Originally it was throwing OOMs, two to three times a week.
  • I want to stop the endless loops of:
    • constantly adding to heap space - which can only go on for so long
    • constant tuning and testing of GC settings - it is long past the point of diminishing return
  • I don't want to treat this like an NT machine and bounce it nightly. There are active user sessions throughout the night, and bouncing the app would mean loosing session data.

To be more specific, I'm looking more for a technique to use to ensure that a Full GC is going to happen, rather than a simple method/function to call to run it.

At the moment I'm looking at the modification of the percentage threshold used by CMS to determine when a Full GC is required.

Thanks for any help.

Jim Black
  • 1,422
  • 1
  • 13
  • 26
  • In general, no, there is no way to force a GC at all -- all you can do is "suggest" one. Though some server JVMs may have extra knobs you can twiddle. (A JVM that does true concurrent GC is the real solution to your problem.) – Hot Licks Jan 02 '14 at 22:42
  • See also http://stackoverflow.com/questions/1481178/forcing-garbage-collection-in-java – Martin Dinov Jan 02 '14 at 22:43
  • Did you experienced any problems with System.gc() or your judgement is based on documentation? Unless explicitly disable using -XX option System.gc() is pretty reliable on my practice. – Alexey Ragozin Jan 03 '14 at 05:50
  • 1
    For the record, the question people are saying this is a duplicate of, doesn't have a marked answer. – Jim Black Jan 03 '14 at 14:29

4 Answers4

21

jmap -histo:live <PID> will force Full GC as "side effect" of finding all live objects. You can schedule it to recycle your JVM processes on off-working hours.

Your JVM build 1.6.0_11-b03 is pretty ancient, but jmap should be supported on all 1.6 HotSpot JVMs.

Alexey Ragozin
  • 8,081
  • 1
  • 23
  • 23
  • This is probably the best answer. Schedule a cron job in the middle of the night to run this command. – MikeG Sep 17 '14 at 21:57
12

No.

System.gc() suggests to the GC that you would like a collection.

Further, there is probably very little garbage generated during the quiet period and that is why calling System.gc() doesn't do much.

During peak time there is, presumably, more activity and therefore more garbage being generated - hence the need for a collection.

It should be obvious that you cannot defer collection in that simplistic manner. The JVM will collect when it needs to.

You need to look into tuning your GC - if you have stop the world collection happening then you have some issue. This shouldn't really happen on a modern server JVM.

You should look into tuning the CMS collector - this is a pretty good article on the basics of the GC system in Java. In Java 7 there is the new G1GC which may or may not be better.

You should find a way to simulate load conditions and try different GC parameters, the CMS GC has many tuning parameters and configuring it is somewhat of a dark art...

This is a somewhat more involved article on GC tuning and benchmarking.

Boris the Spider
  • 59,842
  • 6
  • 106
  • 166
  • 1
    "*there is probably very little garbage generated during the quiet period and that is why calling System.gc() doesn't do much.*" => Not sure I understand - a full GC is a full GC and will GC all garbage accumulated since the last full GC... – assylias Jan 02 '14 at 22:52
  • @assylias I mean that the JVM doesn't let garbage hang around - the GC will happen automatically. So calling the GC during a quiet period won't preclude the GC from being called during a busy period. I suppose an analogy would be that running more trains during off-peak hours won't reduce peak time load. – Boris the Spider Jan 02 '14 at 22:55
  • 1
    No, but bringing all people to where they want just before the rush hour would help. But this analogy doesn't work. Think about emptying the trash bin before many guests arrive. For sure it'll last longer till it fills again and if you're very lucky, it'll survive the whole party. – maaartinus Oct 02 '14 at 13:21
  • 1
    @BoristheSpider The difference is the uptime. There are two major factors: local peaks and total run time. If full GC occurs *only* on the second day of continuous working, than running full GC during midnight has meaning: it would reset the jvm state to the start. This can be fixed without forcing full GC by restarting jvm on midnight. But this is ugly and such awesome runtime as jvm should has some means to clear its state without restarting – ayvango Oct 31 '15 at 17:59
  • 1
    @ayvango a full GC should **never happen**. This is a last resort of the JVM when normal GC (CMS, G1GC etc) has failed to clear sufficient memory. If your application is encountering stop the world GC then you either have a JVM configuration problem or a memory leak - either way, this needs to be addressed. Forcing a full GC at a specific time is the last resort of a Java developer who has no idea how the JVM actually works. – Boris the Spider Nov 01 '15 at 09:46
  • JVM is not a magic. There are always ways to grow garbage infinitely without leaking memory. However smart your heuristics are there are always means to fail them. And that conditions may be formed by a random process. – ayvango Nov 01 '15 at 23:43
3

I'd say yes - schedule a process for your quiet time that does something you believe will trigger a GC.

Eat some serious memory. Allocate a truckload of objects and use weak references to keep track of them - just do something at your quiet time that should trigger a GC.

Do make sure you have in place some logic that detects the GC and stops the process.

OldCurmudgeon
  • 64,482
  • 16
  • 119
  • 213
1

There is no way to force and immediate collection as the garbage collector is non-deterministic.

sasankad
  • 3,543
  • 3
  • 24
  • 31
  • 5
    "non-deterministic" is probably a poor word choice. The GC will run exactly when the JVM's algorithms say that it should be run. If I spent several weeks poring over both the JVM's source and the OP's source, I could figure out when the GC would run based on the OP's garbage generation and the JVM's GC algorithms. That's certainly deterministic. Just because doing that research is a waste of time doesn't mean it can't be done. – Brian S Jan 02 '14 at 23:04