From 4829d14708c0e8ca87d223f604d6502408150c25 Mon Sep 17 00:00:00 2001 From: Sven Diedrichsen Date: Wed, 14 Nov 2018 12:30:37 +0100 Subject: [PATCH] Refactoring synchronizing code to prevent LinkageError to extend fix to EJBHome and Webservice SEI classes. --- .../src/main/java/com/sun/ejb/EJBUtils.java | 187 ++++++++---------- .../com/sun/ejb/containers/BaseContainer.java | 2 +- 2 files changed, 86 insertions(+), 103 deletions(-) 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 ec64a50f951..052c16c26df 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 @@ -57,6 +57,7 @@ import javax.rmi.PortableRemoteObject; import java.io.*; import java.lang.reflect.*; +import java.security.PrivilegedAction; import java.util.Collection; import java.util.Properties; import java.util.SortedMap; @@ -472,8 +473,7 @@ public static Class loadGeneratedSerializableClass(ClassLoader loader, String cl businessInterfaceName); } - public static void loadGeneratedRemoteBusinessClasses - (ClassLoader appClassLoader, String businessInterfaceName) + public static void loadGeneratedRemoteBusinessClasses(ClassLoader appClassLoader, String businessInterfaceName) throws Exception { String generatedRemoteIntfName = EJBUtils. @@ -490,49 +490,33 @@ public static Class loadGeneratedSerializableClass(ClassLoader loader, String cl return; } - // PAYARA-3087 linkage error occurs when multiple threads load the same generated classes concurrently. - synchronized (EJBUtils.class) { - - if (generatedRemoteIntf == null) { - generatedRemoteIntf = loadClassIgnoringExceptions(appClassLoader, generatedRemoteIntfName); - } - if (generatedRemoteWrapper == null) { - generatedRemoteWrapper = loadClassIgnoringExceptions(appClassLoader, wrapperClassName); - } - - if( (generatedRemoteIntf != null) && - (generatedRemoteWrapper != null) ) { - return; - } - - _setClassLoader(appClassLoader); - - try { - if( generatedRemoteIntf == null ) { + _setClassLoader(appClassLoader); - RemoteGenerator gen = new RemoteGenerator(appClassLoader, - businessInterfaceName); + try { + if( generatedRemoteIntf == null ) { - Class developerClass = appClassLoader.loadClass(businessInterfaceName); - generateAndLoad(gen, generatedRemoteIntfName, appClassLoader, developerClass); + RemoteGenerator gen = new RemoteGenerator(appClassLoader, + businessInterfaceName); - } + Class developerClass = appClassLoader.loadClass(businessInterfaceName); + generateAndLoad(gen, generatedRemoteIntfName, appClassLoader, developerClass); - if( generatedRemoteWrapper == null ) { + } - Remote30WrapperGenerator gen = new Remote30WrapperGenerator - (appClassLoader, businessInterfaceName, - generatedRemoteIntfName); + if( generatedRemoteWrapper == null ) { - Class developerClass = appClassLoader.loadClass(businessInterfaceName); - generateAndLoad(gen, wrapperClassName, appClassLoader, developerClass); - } + Remote30WrapperGenerator gen = new Remote30WrapperGenerator + (appClassLoader, businessInterfaceName, + generatedRemoteIntfName); - } finally { - // Fix for 7075: Make sure no classloader is bound to threadlocal: - // avoid possible classloader leak. - _setClassLoader(null) ; + Class developerClass = appClassLoader.loadClass(businessInterfaceName); + generateAndLoad(gen, wrapperClassName, appClassLoader, developerClass); } + + } finally { + // Fix for 7075: Make sure no classloader is bound to threadlocal: + // avoid possible classloader leak. + _setClassLoader(null) ; } } @@ -555,20 +539,11 @@ private static Class loadClassIgnoringExceptions(ClassLoader clsLoader, String c String className = getGenericEJBHomeClassName(); - Class generatedGenericEJBHomeClass = null; - - try { - generatedGenericEJBHomeClass = appClassLoader.loadClass(className); - } catch(Exception e) { - } + Class generatedGenericEJBHomeClass = loadClassIgnoringExceptions(appClassLoader, className); if( generatedGenericEJBHomeClass == null ) { - - GenericHomeGenerator gen =new GenericHomeGenerator(appClassLoader); - - - generatedGenericEJBHomeClass =generateAndLoad(gen, className, - appClassLoader, EJBUtils.class); + GenericHomeGenerator gen = new GenericHomeGenerator(appClassLoader); + generatedGenericEJBHomeClass = generateAndLoad(gen, className, appClassLoader, EJBUtils.class); } return generatedGenericEJBHomeClass; @@ -589,57 +564,70 @@ private static Class generateAndLoad(ClassGeneratorFactory cgf, final ClassLoader loader, final Class protectionDomainBase) { - cgf.evaluate(); + Class clazz = loadClassIgnoringExceptions(loader, actualClassName); - final Properties props = new Properties(); - if( _logger.isLoggable(Level.FINE) ) { + if (clazz != null) { + return clazz; + } - props.put(DUMP_AFTER_SETUP_VISITOR, "true"); - props.put(TRACE_BYTE_CODE_GENERATION, "true"); - props.put(USE_ASM_VERIFIER, "true"); + // PAYARA-3087 LinkageError occurs when multiple threads generate classes + synchronized (EJBUtils.class) { - try { + clazz = loadClassIgnoringExceptions(loader, actualClassName); - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - PrintStream ps = new PrintStream(baos); + if (clazz != null) { + return clazz; + } - _sourceCode(ps, props); - _logger.fine(baos.toString()); + cgf.evaluate(); - } catch(Exception e) { - _logger.log(Level.FINE, "exception generating src", e); - } + 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 | LinkageError 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 + + Class result; try { - result = loader.loadClass(actualClassName); - _logger.log(Level.FINE, "[EJBUtils] Got exception ex: " + runEx - + " but loaded class: " + result.getName()); - } catch (ClassNotFoundException cnfEx) { - throw runEx; + if(System.getSecurityManager() == null) { + result = _generate(loader, protectionDomainBase.getProtectionDomain(), + props); + } else { + result = java.security.AccessController.doPrivileged( + (PrivilegedAction) () -> _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; + return result; + } } @@ -683,16 +671,14 @@ public static RemoteBusinessWrapperBase createRemoteBusinessObject( private static ClassLoader getBusinessIntfClassLoader (String businessInterface) throws Exception { - ClassLoader contextLoader = null; + ClassLoader contextLoader; if(System.getSecurityManager() == null) { ClassLoader cl = Thread.currentThread().getContextClassLoader(); contextLoader = (cl != null) ? cl : ClassLoader.getSystemClassLoader(); } else { - contextLoader = (ClassLoader) - java.security.AccessController.doPrivileged - (new java.security.PrivilegedAction() { - public java.lang.Object run() { + contextLoader = java.security.AccessController.doPrivileged( + (PrivilegedAction) () -> { // Return context class loader. If there is none, // which could happen within Appclient container, // return system class loader. @@ -701,23 +687,20 @@ public java.lang.Object run() { return (cl != null) ? cl : ClassLoader.getSystemClassLoader(); - }}); + } + ); } final Class businessInterfaceClass = contextLoader.loadClass(businessInterface); - ClassLoader appClassLoader = null; + ClassLoader appClassLoader; if(System.getSecurityManager() == null) { appClassLoader = businessInterfaceClass.getClassLoader(); } else { - appClassLoader = (ClassLoader) - java.security.AccessController.doPrivileged - (new java.security.PrivilegedAction() { - public java.lang.Object run() { - return businessInterfaceClass.getClassLoader(); - - }}); + appClassLoader = java.security.AccessController.doPrivileged( + (PrivilegedAction) () -> businessInterfaceClass.getClassLoader() + ); } return appClassLoader; diff --git a/appserver/ejb/ejb-container/src/main/java/com/sun/ejb/containers/BaseContainer.java b/appserver/ejb/ejb-container/src/main/java/com/sun/ejb/containers/BaseContainer.java index 57492b170ae..647eb12e659 100644 --- a/appserver/ejb/ejb-container/src/main/java/com/sun/ejb/containers/BaseContainer.java +++ b/appserver/ejb/ejb-container/src/main/java/com/sun/ejb/containers/BaseContainer.java @@ -1210,7 +1210,7 @@ protected void initializeHome() Class serviceEndpointIntfClass = loader.loadClass(webServiceEndpoint.getServiceEndpointInterface()); - if (!serviceEndpointIntfClass.isInterface()) { + if (serviceEndpointIntfClass == null || !serviceEndpointIntfClass.isInterface()) { ServiceInterfaceGenerator generator = new ServiceInterfaceGenerator(loader, ejbClass); serviceEndpointIntfClass = EJBUtils.generateSEI(generator, generator.getGeneratedClass(), loader, this.ejbClass);