MaxTenuringThreshold - how exactly it works?

Each object in Java heap has a header which is used by Garbage Collection (GC) algorithm. The young space collector (which is responsible for object promotion) uses a few bit(s) from this header to track the number of collections object that have survived (32-bit JVM use 4 bits for this, 64-bit probably some more).

During young space collection, every single object is copied. The Object may be copied to one of survival spaces (one which is empty before young GC) or to the old space. For each object being copied, GC algorithm increases it's age (number of collection survived) and if the age is above the current tenuring threshold it would be copied (promoted) to old space. The Object could also be copied to the old space directly if the survival space gets full (overflow).

The journey of Object has the following pattern:

  • allocated in eden
  • copied from eden to survival space due to young GC
  • copied from survival to (other) survival space due to young GC (this could happen few times)
  • promoted from survival (or possible eden) to old space due to young GC (or full GC)

the actual tenuring threshold is dynamically adjusted by JVM, but MaxTenuringThreshold sets an upper limit on it.

If you set MaxTenuringThreshold=0, all objects will be promoted immediately.

I have few articles about java garbage collection, there you can find more details.


(Disclaimer: This covers HotSpot VM only)

As Alexey states, the actually used tenuring threshold is determined by the JVM dynamically. There is very little value in setting it. For most applications the default value of 15 will be high enough, as usually way more object survive the collection. When many objects survive the collection, the survivor spaces overflow directly to old. This is called premature promotion and an indicator of a problem. However it seldom can be solved by tuning MaxTenuringThreshold.

In those cases sometimes SurvivorRatio might be used to increase the space in the survivor spaces, allowing the tenuring to actually work. However, most often enlarging the young generation is the only good choice (from configuration perspective). If you are looking from coding perspective, you should avoid excess object allocation to let tenuring work as designed.

To answer exactly what you asked: When an object reaches its JVM determinded tenuring threshold, it is copied to old. Before that, it will be copied to the empty survivor space. Objects that have been surviving a while but are de-referenced before reaching the threshold are cleaned from survivor very efficiently.