And a modified pointer to another object is not really a problem. Because the
Dead object can't revive
They really can't help but know which objects are dead? Not! Why?
You do not know this after the initial mark phase, because you look only at the stacks of the streams and do not follow the links.
You do not know if, after the phase of the parallel sign, the following can happen:
- The thread reads the
ax field and stores its value in its register (either on its stack or elsewhere). - Then this thread sets
ax = null (or something else). - GK comes and sees there
null . - The thread then restores
ax to its previous value.
Now GC skipped the ax object. Although the above scenario is not very common, it can happen, and there are more realistic (and more complex) scenarios.
So, you need to look again at the modified memory, which is the phase of the remark. Fortunately, not all memory needs to be scanned again since the map table is used.
I'm afraid this (otherwise nice) explanation is a little misleading at this point:
The remark stage is a stop world. CMS cannot correctly determine which objects are alive (flag them live) if the application is running at the same time and continues to change what is alive.
Streams change what lives, but they also change what you can see as living. And this is the problem.
This article talks about this quite clearly:
Part of the work in the remark phase involves rescanning objects that have been changed by the application stream (i.e., looking at object A to see if A has been changed by the application stream, so that A now refers to another object B and B was not previously marked as live).
I would say: when you look for one room after another, you can skip your glasses when children move them.
Script note
I am sure the above scenario is possible, it’s just not quite what the program usually does. For a fairly realistic example, consider
void swap(Object[] a, int i, int j) { Object tmp = a[i]; a[i] = a[j];