In the loom repo, the following tests have failed with "java.lang.ClassCircularityError: java/util/concurrent/locks/AbstractQueuedSynchronizer$ExclusiveNode".
java/lang/instrument/NativeMethodPrefixAgent.java
runtime/cds/appcds/jigsaw/RedefineClassesInModuleGraph.java
Both have the following stack trace in common:
java.lang.ClassCircularityError: java/util/concurrent/locks/AbstractQueuedSynchronizer$ExclusiveNode
at java.base/java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(AbstractQueuedSynchronizer.java:695)
at java.base/java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(AbstractQueuedSynchronizer.java:938)
at java.base/java.util.concurrent.locks.ReentrantLock$Sync.lock(ReentrantLock.java:153)
at java.base/java.util.concurrent.locks.ReentrantLock.lock(ReentrantLock.java:322)
at java.base/jdk.internal.misc.InternalLock.lock(InternalLock.java:64)
at java.base/java.io.PrintStream.writeln(PrintStream.java:823)
at java.base/java.io.PrintStream.println(PrintStream.java:1167)
at <test app main method>
The root cause is covered by JDK-8164165, which is basically about the issue with the transform() method triggering loading of the class currently being transformed.
AbstractQueuedSynchronizer.acquire(), which is the topmost frame above, has triggered the loading of AbstractQueuedSynchronizer$ExclusiveNode. The test's transform() method is called for AbstractQueuedSynchronizer$ExclusiveNode. The tranform() method does a println(), which result in the same execution path you see above, once again triggering the loading of AbstractQueuedSynchronizer$ExclusiveNode. This results in the CCE.
These failures are new in Loom due to the changes made in the java.io classes to use j.u.concurrent locks instead of synchronized to avoid pinning carrier threads. So now calls to println() end up in j.u.concurrent.