Hi, we observed Java virtual-thread pinning in production when using SAP AI SDK Java 1.22.0.
The JVM was started with:
-Djdk.tracePinnedThreads=full
The pinned-thread trace points to DeploymentResolver.resolveDeployment(...):
VirtualThread[#4188,quarkus-virtual-thread-3623]/runnable@ForkJoinPool-1-worker-5 reason:MONITOR
...
java.base/java.lang.VirtualThread$VThreadContinuation.onPinned
...
java.base/java.util.concurrent.FutureTask.get
...
com.sap.ai.sdk.core.DeploymentResolver.resolveDeployment(DeploymentResolver.java:122) <== monitors:1
com.sap.ai.sdk.core.DeploymentResolver.reloadDeployments(DeploymentResolver.java:50)
com.sap.ai.sdk.core.client.DeploymentApi.query(DeploymentApi.java:754)
org.apache.hc.client5.http.impl.classic.CloseableHttpClient.execute(...)
The relevant code appears to perform a blocking deployment reload while holding a monitor:
synchronized (cache) {
deployment = getCachedDeployment(resourceGroup, predicate);
if (deployment.isPresent()) {
return deployment;
}
reloadDeployments(resourceGroup);
return getCachedDeployment(resourceGroup, predicate);
}
reloadDeployments(...) calls:
val deployments = new HashSet<>(apiClient.query(resourceGroup).getResources());
This means a virtual thread can block on network I/O while inside synchronized (cache), causing reason:MONITOR pinning.
Could this cache reload be changed to avoid blocking I/O while holding the monitor, for example by coordinating reload ownership under lock, releasing the lock during DeploymentApi.query(...), and reacquiring only to update the cache?
Thanks.
Hi, we observed Java virtual-thread pinning in production when using SAP AI SDK Java
1.22.0.The JVM was started with:
The pinned-thread trace points to
DeploymentResolver.resolveDeployment(...):The relevant code appears to perform a blocking deployment reload while holding a monitor:
reloadDeployments(...)calls:This means a virtual thread can block on network I/O while inside
synchronized (cache), causingreason:MONITORpinning.Could this cache reload be changed to avoid blocking I/O while holding the monitor, for example by coordinating reload ownership under lock, releasing the lock during
DeploymentApi.query(...), and reacquiring only to update the cache?Thanks.