This is an automated email from the ASF dual-hosted git repository.

rzo1 pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tomee.git


The following commit(s) were added to refs/heads/main by this push:
     new b7c2145835 Fix deadlock in static initialization of Core introduced 
with #2521 Do not refactor to lambda expressions as it will result in a 
class-initialization deadlock
b7c2145835 is described below

commit b7c2145835e73a72d258b1b9eca36ab3e1638d00
Author: Richard Zowalla <[email protected]>
AuthorDate: Thu Mar 5 08:32:50 2026 +0100

    Fix deadlock in static initialization of Core introduced with #2521
    Do not refactor to lambda expressions as it will result in a 
class-initialization deadlock
---
 .../src/main/java/org/apache/openejb/Core.java     | 52 +++++++++++++++++-----
 1 file changed, 41 insertions(+), 11 deletions(-)

diff --git a/container/openejb-core/src/main/java/org/apache/openejb/Core.java 
b/container/openejb-core/src/main/java/org/apache/openejb/Core.java
index 495f7297b6..6d4c39abfb 100644
--- a/container/openejb-core/src/main/java/org/apache/openejb/Core.java
+++ b/container/openejb-core/src/main/java/org/apache/openejb/Core.java
@@ -26,21 +26,51 @@ import java.util.concurrent.Semaphore;
  * @version $Rev$ $Date$
  */
 public class Core {
+
+    /*
+     * IMPORTANT: Do NOT refactor the anonymous threads in this class to 
lambda expressions.
+     *
+     * Reason:
+     * This code runs during static class initialization. The main thread 
holds the
+     * class-initialization lock for Core while starting worker threads and 
waiting
+     * for them.
+     *
+     * If lambdas are used, the lambda body is compiled into a synthetic method
+     * inside the Core class. When the spawned thread tries to execute the 
lambda,
+     * it must access that synthetic method, which requires Core to be fully
+     * initialized. However, the main thread is still holding the 
initialization
+     * lock and waiting for the worker thread to finish.
+     *
+     * This results in a class-initialization deadlock:
+     *   - Main thread waits for worker thread
+     *   - Worker thread waits for Core initialization to complete
+     *
+     * Anonymous inner classes avoid this problem because they are compiled as
+     * separate classes (e.g. Core$1.class) and can execute without requiring
+     * Core to finish initialization.
+     *
+     */
     static {
-        final Thread preloadMessages = new Thread(() -> {
-            new Messages("org.apache.openejb.util.resources");
-            new Messages("org.apache.openejb.config");
-            new Messages("org.apache.openejb.config.resources");
-        });
+        final Thread preloadMessages = new Thread() {
+            @Override
+            public void run() {
+                new Messages("org.apache.openejb.util.resources");
+                new Messages("org.apache.openejb.config");
+                new Messages("org.apache.openejb.config.resources");
+            }
+        };
         preloadMessages.start();
 
-        final Thread preloadServiceProviders = new Thread(() -> {
-            try {
-                ServiceUtils.getServiceProviders();
-            } catch (final OpenEJBException e) {
-                // no-op
+        final Thread preloadServiceProviders = new Thread() {
+            @Override
+            public void run() {
+                try {
+                    ServiceUtils.getServiceProviders();
+                } catch (final OpenEJBException e) {
+                    // no-op
+                }
             }
-        });
+        };
         preloadServiceProviders.start();
 
         final int permits = 2 * Runtime.getRuntime().availableProcessors() + 1;

Reply via email to