Re: Class unloading in ZGC

Liang Mao at
Mon Dec 7 11:48:53 UTC 2020

 Hi Erik,

Appreciate your comprehensive reply!
I still have few quetion.
> -----Original Message-----
> From: Erik Österlund [mailto:erik.osterlund at]
> Sent: 2020年12月7日 18:35
> To: Liang Mao < at>; zgc-dev <zgc-
> dev at>
> Subject: Re: Class unloading in ZGC
> Hi Liang,
> So there are two distict cases. Class unloading enabled (default), and class
> unloading disabled (seemingly for people that just really want to have memory
> leaks for no apparent good reason).
> When class unloading is enabled, the code cache comprises weak roots, except
> oops that are on-stack that are treated as strong. These semantics are the same
> across all GCs.
> When marking starts, ZGC
> lazily processes the snapshot of nmethods that were on-stack when marking
> started, with lazy application of nmethod entry barriers. These barriers will mark

Sorry that I need to mention I was looking at the code of 8214897: ZGC: Concurrent Class Unloading.
It handled the on-stack nmethod at pause time. Do you mean the pause processing
is not necessary at that patch and the nmethod walking can be delayed as long as nmethod
entry barrier is there? 
On the other hand, if on-stack nmethod is processed at pause time in mark start,  the nmethod
entry barrier is not necessary?


> the objects, and heal the pointers to the corresponding marked color, as
> expected by our barrier machinery. New nmethods that are called go through
> the same processing using nmethod entry barriers. Semantically this ensures that
> on-stack nmethods are treated as strong roots, and the rest of the nmethods
> are treated as weak roots.
> This has the same semantics
> as any other GC.
> When class unloading is disabled, the code cache comprises strong roots.
> That means that the GC will
> during concurrent marking walk all nmethods, and mark the oops as strong.
> However, remember that there are two operations: marking the objects, and
> self-healing the pointers as expected by the barrier machinery.
> The second part of the operation still requires us to lazily apply nmethod entry
> barriers to the stacks as well as arming nmethod entry barriers for calls, during
> concurrent marking, so that the oops in the nmethods are self-healed to the
> corresponding marked pointer color, before they are exposed to the execution
> of mutators, which might for example store this oop into the object graph. So I
> suppose the special thing here compared to G1 is that we both walk the code
> cache marking all the oops, *and* explicitly walk the stacks marking them as
> well, with the main purpose of fixing the pointer colors before the mutator gets
> to use the nmethod. And arming the nmethod entry barriers for calls, for the
> same reason.
> During relocation, we only arm the nmethod entry barriers with and without
> class unloading. The relocation is lazy and won't be performed until either
> someone uses the nmethod (on-stack lazy nmethod entry barrier or a call to a
> new nmethod), or the subsequent marking cycle will walk the code cache and
> make sure that the objects are remapped, when it is performing marking.
> Hope this makes sense and sheds some light on this confusion.
> /Erik
> On 2020-12-06 16:40, Liang Mao wrote:
> > Hi ZGC team,
> >
> > Previously without concurrent class unloading in ZGC, the code cache
> > will be all treated as strong roots. Then concurrent class unloading
> > will only mark the nmethod of executing threads at mark start pause
> > and use the nmethod entry barrier to heal and also mark the oops. That
> > sounds reasonable. But when I looked into the concurrent marking in G1, it
> doesn't threat all code cache as strong roots and of course has no nmethod
> entry barrier. So I'm confused why ZGC need the nmethod entry barrier for
> > marking. Does the difference comes from the different algorithm of SATB vs
> load barrier?
> >
> > Thanks,
> > Liang
> >

More information about the zgc-dev mailing list