The following rule from 5.3.5 is poorly-specified:
---
Otherwise, if any of the superclasses of *C* is *C* itself, loading throws a `ClassCircularityError`.
---
Since C has not been created yet, it is unclear how we might detect that a superclass is "C itself". A naive approach would try to resolve C, then perform a check, but of course attempting to derive C while deriving C would cause a recursive loop or overflow.
The following reflects actual HotSpot behavior for the check:
---
~~Otherwise, if any of the superclasses of *C* is *C* itself~~ **If the
attempt to resolve the direct superclass leads to the current thread
attempting to recursively derive a class named *N* using loader *L***,
loading throws a `ClassCircularityError`.
:::editorial
How can we decide whether a superclass is "*C* itself" without actually
creating the superclass first?
And, of course, we can't create the superclass without recursively
applying this check.
This dependency loop is broken by detecting when a second attempt is
made to derive a class named *N*.
:::
---
and then, to complete the picture in the case of multi-threaded loading, added to Step 5:
---
**If, since step 1, in another thread, the Java Virtual Machine has marked a
class or interface named *N* as having *L* as its defining class loader,
that class or interface is the result of class derivation, and the class or
interface derived in steps 1-4 is discarded.**
---
However, it's not clear whether JVMS has a notion of multiple threads of execution in the context of resolution or class loading. Need to explore further. (And perhaps also add something about multi-threaded resolution to 5.4.3.)