expand
private open fun expand(found: Array<Any>, owners: List<ClassLoader>, host: Set<ClassLoader>): List<ClassLoader>
The plugin loaders plus whatever hangs off their side, cached against the plugin loaders themselves. getPlugins() is cheap enough per lookup — that is what keeps the list live and invalidation-free — but the field scan is not. Keying on the plugin loader list keeps both: enabling, disabling or reloading a plugin changes that list, misses the cache and rescans on its own.
Plugin loaders first, so a plugin's own jar outranks a library or nested-jar copy of the same name. Order only decides genuine duplicates — the gate in load makes every other lookup exclusive.