Fix #23606 java.lang.LinkageError occured when lookup a remote EJB with multiple threads

Signed-off-by: 11rx4f <ryosuke.okada@fujitsu.com>
diff --git a/appserver/ejb/ejb-container/src/main/java/com/sun/ejb/EJBUtils.java b/appserver/ejb/ejb-container/src/main/java/com/sun/ejb/EJBUtils.java
index 08c1dab..6b803a8 100644
--- a/appserver/ejb/ejb-container/src/main/java/com/sun/ejb/EJBUtils.java
+++ b/appserver/ejb/ejb-container/src/main/java/com/sun/ejb/EJBUtils.java
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2021 Contributors to the Eclipse Foundation
  *
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v. 2.0, which is available at
@@ -536,63 +537,81 @@
 
 
     private static Class generateAndLoad(ClassGeneratorFactory cgf,
-                                         final String actualClassName,
-                                         final ClassLoader loader,
-                                         final Class protectionDomainBase) {
-
-        cgf.evaluate();
-
-        final Properties props = new Properties();
-        if( _logger.isLoggable(Level.FINE) ) {
-
-            props.put(DUMP_AFTER_SETUP_VISITOR, "true");
-            props.put(TRACE_BYTE_CODE_GENERATION, "true");
-            props.put(USE_ASM_VERIFIER, "true");
-
-            try {
-
-                ByteArrayOutputStream baos = new ByteArrayOutputStream();
-                PrintStream ps = new PrintStream(baos);
-
-                _sourceCode(ps, props);
-                _logger.fine(baos.toString());
-
-            } catch(Exception e) {
-                _logger.log(Level.FINE, "exception generating src", e);
-            }
-
+            final String actualClassName,
+            final ClassLoader loader,
+            final Class protectionDomainBase) {
+        Class clazz = loadClassIgnoringExceptions(loader, actualClassName);
+        if (clazz != null) {
+            return clazz;
         }
 
-        Class result = null;
-        try {
-            if(System.getSecurityManager() == null) {
-                result = _generate(loader, protectionDomainBase.getProtectionDomain(),
-                                   props);
-            } else {
-                result = (Class)  java.security.AccessController.doPrivileged
-                        (new java.security.PrivilegedAction() {
-                    public java.lang.Object run() {
-                        return  _generate(loader, protectionDomainBase.getProtectionDomain(),
-                                          props);
-                    }});
+        synchronized (EJBUtils.class) {
+            clazz = loadClassIgnoringExceptions(loader, actualClassName);
+            if (clazz != null) {
+                return clazz;
             }
-        } catch (RuntimeException runEx) {
-            //We would have got this exception if there were two (or more)
-            //  concurrent threads that attempted to define the same class
-            //  Lets try to load the class and if we are able to load it
-            //  then we can ignore the exception. Else throw the original exception
-            try {
-                result = loader.loadClass(actualClassName);
-                _logger.log(Level.FINE, "[EJBUtils] Got exception ex: " + runEx
-                        + " but loaded class: " + result.getName());
-            } catch (ClassNotFoundException cnfEx) {
-                throw runEx;
-            }
-        }
 
-        return result;
+            cgf.evaluate();
+
+            final Properties props = new Properties();
+            if (_logger.isLoggable(Level.FINE)) {
+
+                props.put(DUMP_AFTER_SETUP_VISITOR, "true");
+                props.put(TRACE_BYTE_CODE_GENERATION, "true");
+                props.put(USE_ASM_VERIFIER, "true");
+
+                try {
+
+                    ByteArrayOutputStream baos = new ByteArrayOutputStream();
+                    PrintStream ps = new PrintStream(baos);
+
+                    _sourceCode(ps, props);
+                    _logger.fine(baos.toString());
+
+                } catch (Exception e) {
+                    _logger.log(Level.FINE, "exception generating src", e);
+                }
+
+            }
+
+            Class result = null;
+            try {
+                if (System.getSecurityManager() == null) {
+                    result = _generate(loader, protectionDomainBase.getProtectionDomain(),
+                            props);
+                } else {
+                    result = (Class) java.security.AccessController.doPrivileged(new java.security.PrivilegedAction() {
+                        public java.lang.Object run() {
+                            return _generate(loader, protectionDomainBase.getProtectionDomain(),
+                                    props);
+                        }
+                    });
+                }
+            } catch (RuntimeException runEx) {
+                // We would have got this exception if there were two (or more)
+                // concurrent threads that attempted to define the same class
+                // Lets try to load the class and if we are able to load it
+                // then we can ignore the exception. Else throw the original exception
+                try {
+                    result = loader.loadClass(actualClassName);
+                    _logger.log(Level.FINE, "[EJBUtils] Got exception ex: " + runEx
+                            + " but loaded class: " + result.getName());
+                } catch (ClassNotFoundException cnfEx) {
+                    throw runEx;
+                }
+            }
+
+            return result;
+        }
     }
 
+    private static Class loadClassIgnoringExceptions(ClassLoader classLoader, String className) {
+        try {
+            return classLoader.loadClass(className);
+        } catch (Exception e) {
+            return null;
+        }
+    }
 
     public static RemoteBusinessWrapperBase createRemoteBusinessObject
         (String businessInterface, java.rmi.Remote delegate)