In G1ParScanThreadState::copy_to_survivor_state() there is this code that updates the age of the mark. For objects that have a displaced mark the code looks as follows:
if (old_mark->has_displaced_mark_helper()) {
// In this case, we have to install the mark word first,
// otherwise obj looks to be forwarded (the old mark word,
// which contains the forward pointer, was copied)
obj->set_mark(old_mark);
markOop new_mark = old_mark->displaced_mark_helper()->set_age(age);
old_mark->set_displaced_mark_helper(new_mark);
} else {
obj->set_mark(old_mark->set_age(age));
}
The first line copies the old mark to the current object, then the *old_mark*, which is a local variable, is updated.
The age of the obj's mark is never updated.
The impact is that as long as the object is locked (either a lock on stack, or an inflated lock), it won't be aged out into old gen. Typically only a very small amount of objects are locked, so the problem is mostly temporary.
This bug has been introduced in JDK-8064473.