snapshot
target -> the mixins listed under it, copied out from under the processor's monitor.
The monitor is needed because applyMixins is synchronized on it and mutates both configs (an ArrayList, sorted in place — a concurrent walk skips entries and says nothing) and each mixinMapping.
Nothing else may run under it. Class loading here goes class-lock -> the launch plugin's processors -> the processor, so holding the processor and resolving any not-yet-touched class inverts that against the render thread and deadlocks. A first touch is invisible in the source, hence the throwaway unlocked pass: it resolves everything the locked one would have, over the same bytecode and the same branches. Its failure is NOT caught — a pass that did not finish resolved only part of the path, and taking the monitor after that is the deadlock. derive turns the throw into "no overlay", which costs a cast.