Also, to add some more info-- I was looking at what it takes to register a class loader as parallel capable-- as the base class loader class actually behaves differently based on that.
It’s interesting to note that there are 12 classes in Lucee’s core that appear to extend a class loader class of some kind, but only 3 of them appear to register themselves as parallel (noted in bold)
- Lucee/core/src/main/java/lucee/commons/io/res/util/RCL.java
- Lucee/core/src/main/java/lucee/commons/io/res/util/ResourceClassLoader.java (parallel)
- Lucee/core/src/main/java/lucee/commons/lang/ArchiveClassLoader.java
- Lucee/core/src/main/java/lucee/commons/lang/ExtendableClassLoader.java (parallel)
- Lucee/core/src/main/java/lucee/commons/lang/LogClassLoader.java
- Lucee/core/src/main/java/lucee/commons/lang/MemoryClassLoader.java
- Lucee/core/src/main/java/lucee/commons/lang/PClassLoader.java
- Lucee/core/src/main/java/lucee/commons/lang/PCLBlock.java
- Lucee/core/src/main/java/lucee/commons/lang/PhysicalClassLoader.java (parallel)
- Lucee/core/src/main/java/lucee/commons/lang/compiler/DynamicClassLoader.java
- Lucee/core/src/main/java/lucee/runtime/osgi/EnvClassLoader.java
Now, I have NO CLUE if that is causing any issues whatsoever as @micstriit would need to come along and comment on why that was the case. And I’ll point out again your stack shows the locking waiting happening inside of a core JDK class loader-- or at least it appears to. Reading stacks is tricky since if a custom class loader extends java.lang.ClassLoader
and calls its super loadClass()
method, the stack will show the load class method from the core class loader is running, but the actual class loader instance may still be a sub classed instance that has NOT registered itself as parallel capable. So without further debugging, there’s no easy way to tell if the
java.lang.ClassLoader.loadClass(Unknown Source)
call that was waiting on the lock was from an non-parallel-capable subclass or not.
It’s also worth noting that classes such as Lucee’s ExtendableClassLoader
register themselves as parallel capable…
public abstract class ExtendableClassLoader extends ClassLoader {
static {
boolean res = registerAsParallelCapable();
}
...
HOWEVER, this note in the Javadocs for ClassLoader
gives me pause:
* Note that the {@code ClassLoader} class is registered as parallel
* capable by default. However, its subclasses still need to register themselves
* if they are parallel capable.
This seems to imply that simply registering a base class is not enough, but every sub class must also register themselves explicitly as parallel capable. Again, we need @micstriit to chime in here and explain.
@Zackster Also just pointed out this ticket to me which indicates the addition of the parallel code was rather recent (last month). See my comment at the bottom of the ticket based on our discoveries here:
https://luceeserver.atlassian.net/browse/LDEV-4169