From bb96e1d936a9a99fed92f6190048d063e454a7ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Kv=C3=ADdera?= Date: Tue, 26 Jan 2021 03:53:07 +0100 Subject: [PATCH] [FISH-1018] Out of memory redeploy leaks (#5081) * #4098 Reduced too broad scope of variable * #4098 Moved field to local variable - this could be the first cause of leak * #4098 Refactored inner and anonymous classes to nested static classes - anonymous and inner holds implicit reference to parent - this was probably the second cause of leak * #4098 Fixed code consistency * Fix more class loader leaks by: - making sure Server Threads and Timers do not inherit app's context class loaders - making sure app's security contexts don't get propagated to server threads and timers Added correct ear classes to class loader leak tests Co-authored-by: lprimak --- .../concurrent/runtime/ConcurrentRuntime.java | 46 +- .../connectors/ConnectorRuntime.java | 20 +- .../full/deployment/EarClassLoader.java | 12 +- .../javaee/full/deployment/EarDeployer.java | 467 ++++++++++-------- .../full/deployment/EarLibClassLoader.java | 17 +- .../gjc/spi/DSManagedConnectionFactory.java | 22 +- .../com/sun/gjc/spi/ResourceAdapterImpl.java | 19 +- .../classloader-data-api/pom.xml | 6 + .../classloaderdata/InstanceResource.java | 42 +- .../web/loader/WebappClassLoader.java | 33 +- .../common/util/InstanceCounter.java | 2 +- .../v3/server/ApplicationLifecycle.java | 2 +- .../server/logging/GFFileHandler.java | 9 +- .../deployment/admin/DeployCommand.java | 4 +- 14 files changed, 406 insertions(+), 295 deletions(-) diff --git a/appserver/concurrent/concurrent-impl/src/main/java/org/glassfish/concurrent/runtime/ConcurrentRuntime.java b/appserver/concurrent/concurrent-impl/src/main/java/org/glassfish/concurrent/runtime/ConcurrentRuntime.java index 02eb880ca8b..04086835801 100644 --- a/appserver/concurrent/concurrent-impl/src/main/java/org/glassfish/concurrent/runtime/ConcurrentRuntime.java +++ b/appserver/concurrent/concurrent-impl/src/main/java/org/glassfish/concurrent/runtime/ConcurrentRuntime.java @@ -37,13 +37,14 @@ * only if the new code is made subject to such option by the copyright * holder. */ -// Portions Copyright [2016-2018] [Payara Foundation and/or its affiliates] +// Portions Copyright [2016-2021] [Payara Foundation and/or its affiliates] package org.glassfish.concurrent.runtime; import com.sun.enterprise.config.serverbeans.Applications; import com.sun.enterprise.container.common.spi.util.ComponentEnvManager; import com.sun.enterprise.transaction.api.JavaEETransactionManager; +import com.sun.enterprise.util.Utility; import org.glassfish.api.invocation.InvocationManager; import org.glassfish.concurrent.LogFacade; import org.glassfish.concurrent.runtime.deployer.ContextServiceConfig; @@ -65,6 +66,7 @@ import java.util.concurrent.TimeUnit; import java.util.logging.Level; import java.util.logging.Logger; +import org.glassfish.enterprise.concurrent.spi.ContextHandle; /** * This class provides API to create various Concurrency Utilities objects @@ -180,16 +182,16 @@ public void shutdownContextService(String jndiName) { public synchronized ManagedExecutorServiceImpl getManagedExecutorService(ResourceInfo resource, ManagedExecutorServiceConfig config) { String jndiName = config.getJndiName(); - + if (managedExecutorServiceMap != null && managedExecutorServiceMap.containsKey(jndiName)) { return managedExecutorServiceMap.get(jndiName); } - - ManagedThreadFactoryImpl managedThreadFactory = new ManagedThreadFactoryImpl( + + ManagedThreadFactoryImpl managedThreadFactory = new ThreadFactoryWrapper( config.getJndiName() + "-managedThreadFactory", null, config.getThreadPriority()); - + ManagedExecutorServiceImpl mes = new ManagedExecutorServiceImpl(config.getJndiName(), managedThreadFactory, config.getHungAfterSeconds() * 1000L, // in millseconds @@ -202,17 +204,17 @@ public synchronized ManagedExecutorServiceImpl getManagedExecutorService(Resourc createContextService(config.getJndiName() + "-contextservice", config.getContextInfo(), config.getContextInfoEnabled(), true), AbstractManagedExecutorService.RejectPolicy.ABORT); - + if (managedExecutorServiceMap == null) { managedExecutorServiceMap = new HashMap(); } - + managedExecutorServiceMap.put(jndiName, mes); - + if (config.getHungAfterSeconds() > 0L && !config.isLongRunningTasks()) { scheduleInternalTimer(); } - + return mes; } @@ -234,7 +236,7 @@ public synchronized ManagedScheduledExecutorServiceImpl getManagedScheduledExecu if (managedScheduledExecutorServiceMap != null && managedScheduledExecutorServiceMap.containsKey(jndiName)) { return managedScheduledExecutorServiceMap.get(jndiName); } - ManagedThreadFactoryImpl managedThreadFactory = new ManagedThreadFactoryImpl( + ManagedThreadFactoryImpl managedThreadFactory = new ThreadFactoryWrapper( config.getJndiName() + "-managedThreadFactory", null, config.getThreadPriority()); @@ -275,7 +277,7 @@ public synchronized ManagedThreadFactoryImpl getManagedThreadFactory(ResourceInf if (managedThreadFactoryMap != null && managedThreadFactoryMap.containsKey(jndiName)) { return managedThreadFactoryMap.get(jndiName); } - ManagedThreadFactoryImpl managedThreadFactory = new ManagedThreadFactoryImpl(config.getJndiName(), + ManagedThreadFactoryImpl managedThreadFactory = new ThreadFactoryWrapper(config.getJndiName(), createContextService(config.getJndiName() + "-contextservice", config.getContextInfo(), config.getContextInfoEnabled(), true), config.getThreadPriority()); @@ -360,7 +362,7 @@ private ContextSetupProviderImpl.CONTEXT_TYPE[] parseContextInfo(String contextI private void scheduleInternalTimer() { if (internalScheduler == null) { String name = "glassfish-internal"; - ManagedThreadFactoryImpl managedThreadFactory = new ManagedThreadFactoryImpl( + ManagedThreadFactoryImpl managedThreadFactory = new ThreadFactoryWrapper( name + "-managedThreadFactory", null, Thread.NORM_PRIORITY); @@ -378,6 +380,26 @@ private void scheduleInternalTimer() { } } + /** + * context loader propagation to threads causes memory leaks on redeploy + */ + private static final class ThreadFactoryWrapper extends ManagedThreadFactoryImpl { + public ThreadFactoryWrapper(String string, ContextServiceImpl contextService, int threadPriority) { + super(string, contextService, threadPriority); + } + + @Override + protected AbstractManagedThread createThread(Runnable r, ContextHandle contextHandleForSetup) { + ClassLoader appClassLoader = Utility.getClassLoader(); + Utility.setContextClassLoader(null); + try { + return super.createThread(r, contextHandleForSetup); + } finally { + Utility.setContextClassLoader(appClassLoader); + } + } + } + @Override public void postConstruct() { } diff --git a/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/connectors/ConnectorRuntime.java b/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/connectors/ConnectorRuntime.java index f4f93784e0c..f8b1101b416 100755 --- a/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/connectors/ConnectorRuntime.java +++ b/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/connectors/ConnectorRuntime.java @@ -37,7 +37,7 @@ * only if the new code is made subject to such option by the copyright * holder. */ -// Portions Copyright [2019] [Payara Foundation and/or its affiliates] +// Portions Copyright [2019-2021] [Payara Foundation and/or its affiliates] package com.sun.enterprise.connectors; @@ -63,6 +63,7 @@ import com.sun.enterprise.security.SecurityServicesUtil; import com.sun.enterprise.security.jaspic.callback.ContainerCallbackHandler; import com.sun.enterprise.transaction.api.JavaEETransactionManager; +import com.sun.enterprise.util.Utility; import com.sun.logging.LogDomains; import org.glassfish.admin.monitor.MonitoringBootstrap; import org.glassfish.api.admin.ProcessEnvironment; @@ -106,6 +107,8 @@ import javax.transaction.Transaction; import java.io.PrintWriter; import java.net.URI; +import java.security.AccessController; +import java.security.PrivilegedAction; import java.sql.Connection; import java.sql.SQLException; import java.util.*; @@ -886,7 +889,7 @@ public void postConstruct() { } if(isServer() || isEmbedded()){ poolMonitoringLevelListener = poolMonitoringLevelListenerProvider.get(); - + // Force initialization of the ResourceManager getResourceManager(); } @@ -968,7 +971,7 @@ public void createConnectorConnectionPool(ConnectorConnectionPool ccp, throws ConnectorRuntimeException { ccPoolAdmService.createConnectorConnectionPool(ccp, connectionDefinitionName, rarName, props, securityMaps); } - + private synchronized org.glassfish.resourcebase.resources.listener.ResourceManager getResourceManager() { if (resourceManager == null) { try { @@ -978,7 +981,7 @@ private synchronized org.glassfish.resourcebase.resources.listener.ResourceManag return null; } } - + return resourceManager; } @@ -1027,7 +1030,14 @@ public InvocationManager getInvocationManager() { } public Timer getTimer() { - return ConnectorTimerProxy.getProxy(); + ClassLoader appClassLoader = Utility.getClassLoader(); + // prevent app class loader leaking into timer + Utility.setContextClassLoader(null); + try { + return AccessController.doPrivileged((PrivilegedAction) ConnectorTimerProxy::getProxy); + } finally { + Utility.setContextClassLoader(appClassLoader); + } } /** diff --git a/appserver/deployment/javaee-full/src/main/java/org/glassfish/javaee/full/deployment/EarClassLoader.java b/appserver/deployment/javaee-full/src/main/java/org/glassfish/javaee/full/deployment/EarClassLoader.java index 4c1cab7bfb6..f05479e8629 100644 --- a/appserver/deployment/javaee-full/src/main/java/org/glassfish/javaee/full/deployment/EarClassLoader.java +++ b/appserver/deployment/javaee-full/src/main/java/org/glassfish/javaee/full/deployment/EarClassLoader.java @@ -37,7 +37,7 @@ * only if the new code is made subject to such option by the copyright * holder. */ -// Portions Copyright [2016] [Payara Foundation and/or its affiliates] +// Portions Copyright [2016-2021] [Payara Foundation and/or its affiliates] package org.glassfish.javaee.full.deployment; @@ -47,6 +47,7 @@ import com.sun.enterprise.loader.ASURLClassLoader; import java.util.logging.Logger; +import org.glassfish.common.util.InstanceCounter; import org.glassfish.internal.api.DelegatingClassLoader; import org.glassfish.hk2.api.PreDestroy; @@ -62,6 +63,7 @@ public class EarClassLoader extends ASURLClassLoader boolean isPreDestroyCalled = false; private static final Logger log = Logger.getLogger(EarClassLoader.class.getName()); private final Application application; + private final InstanceCounter instanceCounter = new InstanceCounter(this); public EarClassLoader(ClassLoader classLoader, Application application) { super(classLoader); @@ -90,13 +92,13 @@ public void preDestroy() { try { for (ClassLoaderHolder clh : moduleClassLoaders) { // destroy all the module classloaders - if ( !(clh.loader instanceof EarLibClassLoader) && - !(clh.loader instanceof EarClassLoader) && + if ( !(clh.loader instanceof EarLibClassLoader) && + !(clh.loader instanceof EarClassLoader) && !isRARCL(clh.loader)) { try { PreDestroy.class.cast(clh.loader).preDestroy(); } catch (Exception e) { - // ignore, the class loader does not need to be + // ignore, the class loader does not need to be // explicitly stopped. } } @@ -111,7 +113,7 @@ public void preDestroy() { try { PreDestroy.class.cast(cf).preDestroy(); } catch (Exception e) { - // ignore, the class loader does not need to be + // ignore, the class loader does not need to be // explicitly stopped. } } diff --git a/appserver/deployment/javaee-full/src/main/java/org/glassfish/javaee/full/deployment/EarDeployer.java b/appserver/deployment/javaee-full/src/main/java/org/glassfish/javaee/full/deployment/EarDeployer.java index d0668ec52ff..43ca4be4788 100644 --- a/appserver/deployment/javaee-full/src/main/java/org/glassfish/javaee/full/deployment/EarDeployer.java +++ b/appserver/deployment/javaee-full/src/main/java/org/glassfish/javaee/full/deployment/EarDeployer.java @@ -40,25 +40,37 @@ package org.glassfish.javaee.full.deployment; -import org.glassfish.api.deployment.*; +import com.sun.enterprise.deployment.Application; +import com.sun.enterprise.deployment.BundleDescriptor; +import org.glassfish.api.ActionReport.ExitCode; +import org.glassfish.api.admin.ServerEnvironment; +import org.glassfish.api.deployment.ApplicationContainer; +import org.glassfish.api.deployment.DeployCommandParameters; +import org.glassfish.api.deployment.Deployer; +import org.glassfish.api.deployment.DeploymentContext; +import org.glassfish.api.deployment.MetaData; +import org.glassfish.api.deployment.OpsParams; import org.glassfish.api.deployment.archive.ReadableArchive; import org.glassfish.api.deployment.archive.ArchiveHandler; import org.glassfish.api.container.Container; import org.glassfish.api.ActionReport; import org.glassfish.api.event.Events; -import org.glassfish.api.admin.*; import org.glassfish.api.container.Sniffer; -import org.glassfish.deployment.common.*; +import org.glassfish.deployment.common.DeploymentContextImpl; +import org.glassfish.deployment.common.DeploymentException; +import org.glassfish.deployment.common.DummyApplication; +import org.glassfish.deployment.common.RootDeploymentDescriptor; +import org.glassfish.internal.data.ApplicationInfo; +import org.glassfish.internal.data.EngineInfo; +import org.glassfish.internal.data.ModuleInfo; +import org.glassfish.internal.data.ProgressTracker; import org.glassfish.internal.deployment.Deployment; import org.glassfish.internal.deployment.ExtendedDeploymentContext; -import org.glassfish.internal.data.*; -import org.glassfish.internal.deployment.SnifferManager; -import org.glassfish.hk2.classmodel.reflect.*; import org.jvnet.hk2.annotations.Service; + import javax.inject.Inject; import org.glassfish.hk2.api.PerLookup; -import com.sun.enterprise.deployment.*; import com.sun.enterprise.deployment.util.DOLUtils; import org.glassfish.deployment.common.ModuleDescriptor; import org.glassfish.api.deployment.archive.ArchiveType; @@ -66,12 +78,16 @@ import com.sun.enterprise.deployment.deploy.shared.Util; import com.sun.enterprise.util.LocalStringManagerImpl; -import java.util.*; +import java.util.Collection; +import java.util.Hashtable; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Properties; import java.util.logging.Logger; import java.util.logging.Level; import java.io.IOException; import java.io.File; -import java.net.URI; import org.glassfish.logging.annotation.LogMessageInfo; import org.glassfish.logging.annotation.LoggerInfo; @@ -87,7 +103,7 @@ @PerLookup public class EarDeployer implements Deployer { -// private static final Class GLASSFISH_APPCLIENT_GROUP_FACADE_CLASS = + // private static final Class GLASSFISH_APPCLIENT_GROUP_FACADE_CLASS = // org.glassfish.appclient.client.AppClientGroupFacade.class; // Currently using a string instead of a Class constant to avoid a circular // dependency. @@ -97,12 +113,6 @@ public class EarDeployer implements Deployer { @Inject ServerEnvironment env; - @Inject - ApplicationRegistry appRegistry; - - @Inject - protected SnifferManager snifferManager; - @Inject ArchiveFactory archiveFactory; @@ -114,22 +124,22 @@ public class EarDeployer implements Deployer { // Reserve this range [AS-DEPLOYMENT-02001, AS-DEPLOYMENT-04000] // for message ids used in this deployment javaee-full module - @LoggerInfo(subsystem = "DEPLOYMENT", description="Deployment logger for javaee-full module", publish=true) + @LoggerInfo(subsystem = "DEPLOYMENT", description = "Deployment logger for javaee-full module", publish = true) private static final String DEPLOYMENT_LOGGER = "javax.enterprise.system.tools.deployment.javaeefull"; public static final Logger deplLogger = Logger.getLogger(DEPLOYMENT_LOGGER, SHARED_LOGMESSAGE_RESOURCE); - @LogMessageInfo(message = "Skipped processing for module {0} as its module type was not recognized", level="WARNING") + @LogMessageInfo(message = "Skipped processing for module {0} as its module type was not recognized", level = "WARNING") private static final String UNRECOGNIZED_MODULE_TYPE = "AS-DEPLOYMENT-02015"; - @LogMessageInfo(message = "Error occurred", level="WARNING") + @LogMessageInfo(message = "Error occurred", level = "WARNING") private static final String ERROR_OCCURRED = "AS-DEPLOYMENT-02016"; final private static LocalStringManagerImpl localStrings = new LocalStringManagerImpl(EarDeployer.class); public MetaData getMetaData() { - return new MetaData(false, null, new Class[] { Application.class}); + return new MetaData(false, null, new Class[]{Application.class}); } public Object loadMetaData(Class type, DeploymentContext context) { @@ -142,43 +152,40 @@ public boolean prepare(final DeploymentContext context) { DeployCommandParameters deployParams = context.getCommandParameters(DeployCommandParameters.class); final String appName = deployParams.name(); - - final ApplicationInfo appInfo = new CompositeApplicationInfo(events, application, context.getSource(), appName); + + final CompositeApplicationInfo appInfo = + new CompositeApplicationInfo(events, application, context.getSource(), appName, archiveFactory, env); for (Object m : context.getModuleMetadata()) { appInfo.addMetaData(m); } try { - doOnAllBundles(application, new BundleBlock() { - public ModuleInfo doBundle(ModuleDescriptor bundle) throws Exception { - ExtendedDeploymentContext sContext = subContext(application, context, bundle.getArchiveUri()); - ModuleInfo info = prepareBundle(bundle, application, - sContext); - if (info == null) { - sContext.getActionReport().setActionExitCode(ActionReport.ExitCode.WARNING); - String msg = localStrings.getLocalString("skipmoduleprocessing", "Skipped processing for module {0} as its module type was not recognized", bundle.getArchiveUri()); - sContext.getActionReport().setMessage(msg); - deplLogger.log(Level.WARNING, - UNRECOGNIZED_MODULE_TYPE, - bundle.getArchiveUri()); - return null; - } - info.addMetaData(application); - BundleDescriptor bundleDesc = application.getModuleByUri( + doOnAllBundles(application, (BundleBlock) bundle -> { + ExtendedDeploymentContext sContext = appInfo.subContext(application, context, bundle.getArchiveUri()); + ModuleInfo info = prepareBundle(bundle, application, sContext); + if (info == null) { + sContext.getActionReport().setActionExitCode(ExitCode.WARNING); + String msg = localStrings.getLocalString("skipmoduleprocessing", "Skipped processing for module {0} as its module type was not recognized", bundle.getArchiveUri()); + sContext.getActionReport().setMessage(msg); + deplLogger.log(Level.WARNING, + UNRECOGNIZED_MODULE_TYPE, bundle.getArchiveUri()); - info.addMetaData(bundleDesc); - for (RootDeploymentDescriptor ext : - bundleDesc.getExtensionsDescriptors()) { - info.addMetaData(ext); - } - appInfo.addModule(info); - return info; + return null; } - + info.addMetaData(application); + BundleDescriptor bundleDesc = application.getModuleByUri( + bundle.getArchiveUri()); + info.addMetaData(bundleDesc); + for (RootDeploymentDescriptor ext : + bundleDesc.getExtensionsDescriptors()) { + info.addMetaData(ext); + } + appInfo.addModule(info); + return info; }); - } catch(DeploymentException dde) { + } catch (DeploymentException dde) { throw dde; - } catch(Exception e) { + } catch (Exception e) { DeploymentException de = new DeploymentException(e.getMessage()); de.initCause(e); throw de; @@ -199,43 +206,29 @@ protected void generateArtifacts(final DeploymentContext context) throws Deploym * facade. */ } - - - private class CompositeApplicationInfo extends ApplicationInfo { - - final Application application; - - private CompositeApplicationInfo(Events events, Application application, ReadableArchive source, String name) { - super(events, source, name); - this.application = application; - } - - @Override - protected ExtendedDeploymentContext getSubContext(ModuleInfo module, ExtendedDeploymentContext context) { - return subContext(application, context, module.getName()); - } - - } /** * Performs the same runnable task on each specified bundle. * - * @param bundles the bundles on which to perform the task + * @param bundles the bundles on which to perform the task * @param runnable the task to perform * @throws Exception */ private void doOnBundles( - final Collection> bundles, - final BundleBlock runnable) throws Exception { + final Collection> bundles, + final BundleBlock runnable) throws Exception { for (ModuleDescriptor module : bundles) { runnable.doBundle(module); } } - private Collection> - doOnAllTypedBundles(Application application, ArchiveType type, BundleBlock runnable) - throws Exception { + private Collection> doOnAllTypedBundles( + Application application, + ArchiveType type, + BundleBlock runnable + ) + throws Exception { final Collection> typedBundles = application.getModuleDescriptorsByType(type); doOnBundles(typedBundles, runnable); @@ -244,7 +237,7 @@ private void doOnBundles( private void doOnAllBundles(Application application, BundleBlock runnable) throws Exception { - Collection bundles = + Collection bundles = new LinkedHashSet(); bundles.addAll(application.getModules()); @@ -255,7 +248,7 @@ private void doOnAllBundles(Application application, BundleBlock runnable) throw runnable.doBundle(bundle); } } - + // otherwise we load modules by default order: connector, ejb, web and // saving app client for last (because other submodules might generated // artifacts that should be included in the generated app client JAR @@ -271,9 +264,9 @@ private void doOnAllBundles(Application application, BundleBlock runnable) throw // extract the app client bundles to take care of later Collection> appClientBundles = - application.getModuleDescriptorsByType(DOLUtils.carType()); + application.getModuleDescriptorsByType(DOLUtils.carType()); bundles.removeAll(appClientBundles); - + // now ther remaining bundles for (final ModuleDescriptor bundle : bundles) { runnable.doBundle(bundle); @@ -281,13 +274,13 @@ private void doOnAllBundles(Application application, BundleBlock runnable) throw // Last, deal with the app client bundles doOnBundles(appClientBundles, runnable); - } + } } private ModuleInfo prepareBundle(final ModuleDescriptor md, Application application, final ExtendedDeploymentContext bundleContext) throws Exception { - List orderedContainers = null; + List orderedContainers; ProgressTracker tracker = bundleContext.getTransientAppMetaData(ExtendedDeploymentContext.TRACKER, ProgressTracker.class); @@ -300,10 +293,10 @@ private ModuleInfo prepareBundle(final ModuleDescriptor md, Application applicat if (orderedContainers == null) { return null; } - } catch(Exception e) { + } catch (Exception e) { deplLogger.log(Level.WARNING, - ERROR_OCCURRED, - e); + ERROR_OCCURRED, + e); throw e; } return deployment.prepareModule(orderedContainers, md.getArchiveUri(), bundleContext, tracker); @@ -324,159 +317,205 @@ public void clean(DeploymentContext context) { private interface BundleBlock { - public T doBundle(ModuleDescriptor bundle) throws Exception; + T doBundle(ModuleDescriptor bundle) throws Exception; } - - private ExtendedDeploymentContext subContext(final Application application, final DeploymentContext context, final String moduleUri) { - - ExtendedDeploymentContext moduleContext = ((ExtendedDeploymentContext)context).getModuleDeploymentContexts().get(moduleUri); - if (moduleContext != null) { - return moduleContext; - } + private static Properties getModuleProps(DeploymentContext context, String moduleUri) { + Map modulePropsMap = context.getModulePropsMap(); + Properties moduleProps = modulePropsMap.get(moduleUri); + if (moduleProps == null) { + moduleProps = new Properties(); + modulePropsMap.put(moduleUri, moduleProps); + } + return moduleProps; + } - final ReadableArchive subArchive; - try { - subArchive = context.getSource().getSubArchive(moduleUri); - subArchive.setParentArchive(context.getSource()); - } catch(IOException ioe) { - deplLogger.log(Level.WARNING, - ERROR_OCCURRED, - ioe); + private static class CompositeApplicationInfo extends ApplicationInfo { + + private final Application application; + private ArchiveFactory archiveFactory; + private ServerEnvironment env; + + private CompositeApplicationInfo( + final Events events, + final Application application, + final ReadableArchive source, + final String name, + final ArchiveFactory archiveFactory, + final ServerEnvironment env + ) { + super(events, source, name); + this.application = application; + this.archiveFactory = archiveFactory; + this.env = env; + } + + @Override + protected ExtendedDeploymentContext getSubContext(ModuleInfo module, ExtendedDeploymentContext context) { + return subContext(application, context, module.getName()); + } + + private ExtendedDeploymentContext subContext(final Application application, final DeploymentContext context, final String moduleUri) { + + ExtendedDeploymentContext moduleContext = ((ExtendedDeploymentContext) context).getModuleDeploymentContexts().get(moduleUri); + if (moduleContext != null) { + return moduleContext; + } + + + final ReadableArchive subArchive; + try { + subArchive = context.getSource().getSubArchive(moduleUri); + subArchive.setParentArchive(context.getSource()); + } catch (IOException ioe) { + deplLogger.log(Level.WARNING, + ERROR_OCCURRED, + ioe); + return null; + } + + ActionReport subReport = + context.getActionReport().addSubActionsReport(); + moduleContext = new EarDeployerDeploymentContextImpl(subReport, context, moduleUri, subArchive, env, archiveFactory, application); + + ((ExtendedDeploymentContext) context).getModuleDeploymentContexts().put(moduleUri, moduleContext); + moduleContext.setParentContext((ExtendedDeploymentContext) context); + moduleContext.setModuleUri(moduleUri); + ArchiveHandler subHandler = context.getModuleArchiveHandlers().get(moduleUri); + moduleContext.setArchiveHandler(subHandler); + + return moduleContext; + } + } + + private static class EarDeployerDeploymentContextImpl extends DeploymentContextImpl { + private final DeploymentContext context; + private final String moduleUri; + private final ReadableArchive subArchive; + private final ArchiveFactory archiveFactory; + private final Application application; + + public EarDeployerDeploymentContextImpl( + final ActionReport subReport, + final DeploymentContext context, + final String moduleUri, + final ReadableArchive subArchive, + final ServerEnvironment env, + final ArchiveFactory archiveFactory, + final Application application + ) { + super(subReport, context.getSource(), context.getCommandParameters(OpsParams.class), env); + this.context = context; + this.moduleUri = moduleUri; + this.subArchive = subArchive; + this.archiveFactory = archiveFactory; + this.application = application; + } + + + @Override + public ClassLoader getClassLoader() { + try { + if (context.getClassLoader() == null) { return null; } - - final Properties moduleProps = - getModuleProps(context, moduleUri); - - ActionReport subReport = - context.getActionReport().addSubActionsReport(); - moduleContext = new DeploymentContextImpl(subReport, context.getSource(), - context.getCommandParameters(OpsParams.class), env) { - - @Override - public ClassLoader getClassLoader() { - try { - if (context.getClassLoader() == null) { - return null; - } - EarClassLoader appCl = EarClassLoader.class.cast(context.getClassLoader()); - if (((ExtendedDeploymentContext)context). - getPhase() == Phase.PREPARE) { - return appCl; - } else { - return appCl.getModuleClassLoader(moduleUri); - } - } catch (ClassCastException e) { - return context.getClassLoader(); - } - } + EarClassLoader appCl = EarClassLoader.class.cast(context.getClassLoader()); + if (((ExtendedDeploymentContext) context).getPhase() == Phase.PREPARE) { + return appCl; + } else { + return appCl.getModuleClassLoader(moduleUri); + } + } catch (ClassCastException e) { + return context.getClassLoader(); + } + } - @Override - public ClassLoader getFinalClassLoader() { - try { - EarClassLoader finalEarCL = (EarClassLoader) context.getFinalClassLoader(); - return finalEarCL.getModuleClassLoader(moduleUri); - } catch (ClassCastException e) { - return context.getClassLoader(); - } - } - @Override - public ReadableArchive getSource() { - return subArchive; - } + @Override + public ClassLoader getFinalClassLoader() { + try { + EarClassLoader finalEarCL = (EarClassLoader) context.getFinalClassLoader(); + return finalEarCL.getModuleClassLoader(moduleUri); + } catch (ClassCastException e) { + return context.getClassLoader(); + } + } - @Override - public Properties getAppProps() { - return context.getAppProps(); - } + @Override + public ReadableArchive getSource() { + return subArchive; + } - @Override - public U getCommandParameters(Class commandParametersType) { - return context.getCommandParameters(commandParametersType); - } + @Override + public Properties getAppProps() { + return context.getAppProps(); + } - @Override - public void addTransientAppMetaData(String metaDataKey, - Object metaData) { - context.addTransientAppMetaData(metaDataKey, - metaData); - } + @Override + public U getCommandParameters(Class commandParametersType) { + return context.getCommandParameters(commandParametersType); + } - @Override - public T getTransientAppMetaData(String metaDataKey, - Class metadataType) { - return context.getTransientAppMetaData(metaDataKey, - metadataType); - } + @Override + public void addTransientAppMetaData(String metaDataKey, + Object metaData) { + context.addTransientAppMetaData(metaDataKey, + metaData); + } - @Override - public Properties getModuleProps() { - return moduleProps; - } + @Override + public T getTransientAppMetaData(String metaDataKey, + Class metadataType) { + return context.getTransientAppMetaData(metaDataKey, + metadataType); + } - @Override - public ReadableArchive getOriginalSource() { - try { - File appRoot = context.getSourceDir(); - File origModuleFile = new File(appRoot, moduleUri); - return archiveFactory.openArchive( - origModuleFile); - } catch (IOException ioe) { - return null; - } - } + @Override + public Properties getModuleProps() { + return EarDeployer.getModuleProps(context, moduleUri); + } - @Override - public File getScratchDir(String subDirName) { - String modulePortion = Util.getURIName( - getSource().getURI()); - return (new File(super.getScratchDir(subDirName), - modulePortion)); - } + @Override + public ReadableArchive getOriginalSource() { + try { + File appRoot = context.getSourceDir(); + File origModuleFile = new File(appRoot, moduleUri); + return archiveFactory.openArchive( + origModuleFile); + } catch (IOException ioe) { + return null; + } + } - @Override - public T getModuleMetaData(Class metadataType) { - try { - return metadataType.cast(application.getModuleByUri(moduleUri)); - } catch (Exception e) { - // let's first try the extensions mechanisms... - if (RootDeploymentDescriptor.class.isAssignableFrom(metadataType)) { - for (RootDeploymentDescriptor extension : application.getModuleByUri(moduleUri).getExtensionsDescriptors((Class) metadataType)) { - // we assume there can only be one type of - if (extension!=null) { - try { - return metadataType.cast(extension); - } catch (Exception e1) { - // next one... - } - } - } - - } + @Override + public File getScratchDir(String subDirName) { + String modulePortion = Util.getURIName( + getSource().getURI()); + return (new File(super.getScratchDir(subDirName), + modulePortion)); + } - return context.getModuleMetaData(metadataType); + @Override + public T getModuleMetaData(Class metadataType) { + try { + return metadataType.cast(application.getModuleByUri(moduleUri)); + } catch (Exception e) { + // let's first try the extensions mechanisms... + if (RootDeploymentDescriptor.class.isAssignableFrom(metadataType)) { + for (RootDeploymentDescriptor extension : application.getModuleByUri(moduleUri).getExtensionsDescriptors((Class) metadataType)) { + // we assume there can only be one type of + if (extension != null) { + try { + return metadataType.cast(extension); + } catch (Exception e1) { + // next one... + } } } - }; - - ((ExtendedDeploymentContext)context).getModuleDeploymentContexts().put(moduleUri, moduleContext); - moduleContext.setParentContext((ExtendedDeploymentContext)context); - moduleContext.setModuleUri(moduleUri); - ArchiveHandler subHandler = context.getModuleArchiveHandlers().get(moduleUri); - moduleContext.setArchiveHandler(subHandler); - return moduleContext; - } + } - private Properties getModuleProps(DeploymentContext context, - String moduleUri) { - Map modulePropsMap = context.getModulePropsMap(); - Properties moduleProps = modulePropsMap.get(moduleUri); - if (moduleProps == null) { - moduleProps = new Properties(); - modulePropsMap.put(moduleUri, moduleProps); + return context.getModuleMetaData(metadataType); + } } - return moduleProps; } } diff --git a/appserver/deployment/javaee-full/src/main/java/org/glassfish/javaee/full/deployment/EarLibClassLoader.java b/appserver/deployment/javaee-full/src/main/java/org/glassfish/javaee/full/deployment/EarLibClassLoader.java index 7b8ac8da96c..c01853d1949 100644 --- a/appserver/deployment/javaee-full/src/main/java/org/glassfish/javaee/full/deployment/EarLibClassLoader.java +++ b/appserver/deployment/javaee-full/src/main/java/org/glassfish/javaee/full/deployment/EarLibClassLoader.java @@ -37,7 +37,7 @@ * only if the new code is made subject to such option by the copyright * holder. */ - // Portions Copyright [2016-2019] [Payara Foundation and/or its affiliates] + // Portions Copyright [2016-2021] [Payara Foundation and/or its affiliates] package org.glassfish.javaee.full.deployment; @@ -48,6 +48,7 @@ import java.util.Collections; import java.util.Enumeration; import java.util.List; +import org.glassfish.common.util.InstanceCounter; /** * Classloader that is responsible to load the ear libraries (lib/*.jar etc) @@ -55,8 +56,10 @@ */ public class EarLibClassLoader extends ASURLClassLoader { + private final InstanceCounter instanceCounter = new InstanceCounter(this); + public EarLibClassLoader(URL[] urls, ClassLoader classLoader) { - super(classLoader); + super(classLoader); enableCurrentBeforeParent(); for (URL url : urls) { super.addURL(url); @@ -67,24 +70,24 @@ public EarLibClassLoader(URL[] urls, ClassLoader classLoader) { * The below loads services from META-INF from the libraries, * so we want to take these from the EAR libraries, * this does similar to what WebappClassLoader does - * + * * @param name * @return set of resources URLSs - * @throws IOException + * @throws IOException */ @Override public Enumeration getResources(String name) throws IOException { Enumeration localResources = super.getResources(name); Enumeration parentResources = getParent().getResources(name); - + Enumeration combined = Collections.emptyEnumeration(); - + Enumeration combinedResources = currentBeforeParentEnabled? combineEnumerations(localResources, parentResources): combineEnumerations(parentResources, localResources); return combinedResources; } - + private Enumeration combineEnumerations(Enumeration first, Enumeration second) { List combinedList = new ArrayList<>(); while (first.hasMoreElements()) { diff --git a/appserver/jdbc/jdbc-ra/jdbc-core/src/main/java/com/sun/gjc/spi/DSManagedConnectionFactory.java b/appserver/jdbc/jdbc-ra/jdbc-core/src/main/java/com/sun/gjc/spi/DSManagedConnectionFactory.java index 2a605c01835..40bb895b995 100644 --- a/appserver/jdbc/jdbc-ra/jdbc-core/src/main/java/com/sun/gjc/spi/DSManagedConnectionFactory.java +++ b/appserver/jdbc/jdbc-ra/jdbc-core/src/main/java/com/sun/gjc/spi/DSManagedConnectionFactory.java @@ -37,14 +37,18 @@ * only if the new code is made subject to such option by the copyright * holder. */ -// Portions Copyright [2016-2019] [Payara Foundation and/or its affiliates] +// Portions Copyright [2016-2021] [Payara Foundation and/or its affiliates] package com.sun.gjc.spi; +import com.sun.enterprise.util.Utility; import com.sun.enterprise.util.i18n.StringManager; import com.sun.gjc.common.DataSourceObjectBuilder; import com.sun.gjc.util.SecurityUtils; import com.sun.logging.LogDomains; +import java.security.AccessController; +import java.security.PrivilegedActionException; +import java.security.PrivilegedExceptionAction; import javax.resource.ResourceException; import javax.resource.spi.ConnectionRequestInfo; @@ -106,6 +110,10 @@ public javax.resource.spi.ManagedConnection createManagedConnection(javax.securi java.sql.Connection dsConn = null; ManagedConnectionImpl mc = null; + ClassLoader appClassLoader = Utility.getClassLoader(); + // do not propagate application class loader to the database driver + // may cause memory leaks in embedded databases + Utility.setContextClassLoader(null); try { /* For the case where the user/passwd of the connection pool is * equal to the PasswordCredential for the connection request @@ -114,12 +122,14 @@ public javax.resource.spi.ManagedConnection createManagedConnection(javax.securi */ String user = getUser(); if (user == null || isEqual(pc, user, getPassword())) { - dsConn = dataSource.getConnection(); + dsConn = AccessController.doPrivileged((PrivilegedExceptionAction) dataSource::getConnection); } else { - dsConn = dataSource.getConnection(pc.getUserName(), - new String(pc.getPassword())); + dsConn = AccessController.doPrivileged((PrivilegedExceptionAction) () -> + dataSource.getConnection(pc.getUserName(), + new String(pc.getPassword()))); } - } catch (java.sql.SQLException sqle) { + } catch (PrivilegedActionException ex) { + java.sql.SQLException sqle = (SQLException)ex.getCause(); //_logger.log(Level.WARNING, "jdbc.exc_create_conn", sqle.getMessage()); if(_logger.isLoggable(Level.FINE)) { _logger.log(Level.FINE, "jdbc.exc_create_conn", sqle.getMessage()); @@ -131,6 +141,8 @@ public javax.resource.spi.ManagedConnection createManagedConnection(javax.securi ResourceAllocationException rae = new ResourceAllocationException(msg); rae.initCause(sqle); throw rae; + } finally { + Utility.setContextClassLoader(appClassLoader); } try { diff --git a/appserver/jdbc/jdbc-ra/jdbc-core/src/main/java/com/sun/gjc/spi/ResourceAdapterImpl.java b/appserver/jdbc/jdbc-ra/jdbc-core/src/main/java/com/sun/gjc/spi/ResourceAdapterImpl.java index 3bdc735b8cd..a173db270d8 100644 --- a/appserver/jdbc/jdbc-ra/jdbc-core/src/main/java/com/sun/gjc/spi/ResourceAdapterImpl.java +++ b/appserver/jdbc/jdbc-ra/jdbc-core/src/main/java/com/sun/gjc/spi/ResourceAdapterImpl.java @@ -37,11 +37,15 @@ * only if the new code is made subject to such option by the copyright * holder. */ -// Portions Copyright [2018] Payara Foundation and/or affiliates +// Portions Copyright [2018-2021] Payara Foundation and/or affiliates package com.sun.gjc.spi; +import com.sun.enterprise.util.Utility; import com.sun.logging.LogDomains; +import java.security.AccessController; +import java.security.PrivilegedActionException; +import java.security.PrivilegedExceptionAction; import java.util.Timer; import java.util.logging.Level; import java.util.logging.Logger; @@ -50,7 +54,6 @@ import javax.resource.spi.AuthenticationMechanism; import javax.resource.spi.BootstrapContext; import javax.resource.spi.Connector; -import javax.resource.spi.UnavailableException; import javax.resource.spi.endpoint.MessageEndpointFactory; import javax.transaction.xa.XAResource; @@ -159,10 +162,16 @@ public Timer getTimer() { if(_logger.isLoggable(Level.FINEST)) { _logger.finest("Creating the timer"); } + ClassLoader appClassLoader = Utility.getClassLoader(); + // do not propagate application class loader to the timer thread + // may cause memory leaks + Utility.setContextClassLoader(null); try { - timer = bootstrapContext.createTimer(); - } catch (UnavailableException ex) { - _logger.log(Level.SEVERE, "jdbc-ra.timer_creation_exception", ex.getMessage()); + timer = AccessController.doPrivileged((PrivilegedExceptionAction) bootstrapContext::createTimer); + } catch (PrivilegedActionException ex) { + _logger.log(Level.SEVERE, "jdbc-ra.timer_creation_exception", ex.getCause().getMessage()); + } finally { + Utility.setContextClassLoader(appClassLoader); } } } diff --git a/appserver/tests/payara-samples/classloader-data-api/pom.xml b/appserver/tests/payara-samples/classloader-data-api/pom.xml index 45317fe5ec5..b84dddb589c 100644 --- a/appserver/tests/payara-samples/classloader-data-api/pom.xml +++ b/appserver/tests/payara-samples/classloader-data-api/pom.xml @@ -29,6 +29,12 @@ ${project.version} provided + + fish.payara.server.internal.deployment + deployment-javaee-full + ${project.version} + provided + jakarta.platform jakarta.jakartaee-api diff --git a/appserver/tests/payara-samples/classloader-data-api/src/main/java/fish/payara/samples/classloaderdata/InstanceResource.java b/appserver/tests/payara-samples/classloader-data-api/src/main/java/fish/payara/samples/classloaderdata/InstanceResource.java index f463e78bb36..da193cfafbf 100644 --- a/appserver/tests/payara-samples/classloader-data-api/src/main/java/fish/payara/samples/classloaderdata/InstanceResource.java +++ b/appserver/tests/payara-samples/classloader-data-api/src/main/java/fish/payara/samples/classloaderdata/InstanceResource.java @@ -1,7 +1,7 @@ /* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * - * Copyright (c) [2020] Payara Foundation and/or its affiliates. All rights reserved. + * Copyright (c) [2020-2021] Payara Foundation and/or its affiliates. All rights reserved. * * The contents of this file are subject to the terms of either the GNU * General Public License Version 2 only ("GPL") or the Common Development @@ -39,18 +39,18 @@ */ package fish.payara.samples.classloaderdata; -import com.sun.enterprise.loader.ASURLClassLoader; import java.lang.ref.WeakReference; import java.util.Objects; import java.util.Optional; -import java.util.function.Consumer; -import java.util.function.Supplier; +import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.Collectors; import javax.enterprise.context.ApplicationScoped; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import org.glassfish.common.util.InstanceCounter; +import org.glassfish.javaee.full.deployment.EarClassLoader; +import org.glassfish.javaee.full.deployment.EarLibClassLoader; import org.glassfish.web.loader.WebappClassLoader; /** * A simple REST endpoint to return the count of @@ -61,37 +61,41 @@ @Path("instance-count") @ApplicationScoped public class InstanceResource { - private Integer previousWebappInstanceCount; - private Integer previousASURLInstanceCount; + private final AtomicInteger previousWebappInstanceCount = new AtomicInteger(-1); + private final AtomicInteger previousEarInstanceCount = new AtomicInteger(-1); + private final AtomicInteger previousEarLibInstanceCount = new AtomicInteger(-1); /** * Method handling HTTP GET request for Instance Count * Example: curl http://localhost:8080/ClassloaderDataAPI/api/instance-count/webapp/ - * Example: curl http://localhost:8080/ClassloaderDataAPI/api/instance-count/asurl/500 + * Example: curl http://localhost:8080/ClassloaderDataAPI/api/instance-count/ear/ + * Example: curl http://localhost:8080/ClassloaderDataAPI/api/instance-count/earlib/500 */ @GET @Path("/webapp/{timeout:.*}") public String getWebappClassLoaderCount(@PathParam("timeout") Long timeout) { - return instanceGetter(WebappClassLoader.class, () -> previousWebappInstanceCount, - newValue -> previousWebappInstanceCount = newValue, timeout); + return instanceGetter(WebappClassLoader.class, previousWebappInstanceCount, timeout); } @GET - @Path("/asurl/{timeout:.*}") - public String getPreviousInstanceCount(@PathParam("timeout") Long timeout) { - return instanceGetter(ASURLClassLoader.class, () -> previousASURLInstanceCount, - newValue -> previousASURLInstanceCount = newValue, timeout); + @Path("/ear/{timeout:.*}") + public String getEarClassLoaderCount(@PathParam("timeout") Long timeout) { + return instanceGetter(EarClassLoader.class, previousEarInstanceCount, timeout); } - private static String instanceGetter(Class clazz, - Supplier previousCountSupplier, Consumer previousCountConsumer, - Long _timeout) { + @GET + @Path("/earlib/{timeout:.*}") + public String getEarLibClassLoaderCount(@PathParam("timeout") Long timeout) { + return instanceGetter(EarLibClassLoader.class, previousEarLibInstanceCount, timeout); + } + + private static String instanceGetter(Class clazz, AtomicInteger previousValue, Long _timeout) { long timeout = Optional.ofNullable(_timeout).orElse(1L); - int previous = Optional.ofNullable(previousCountSupplier.get()).orElse(InstanceCounter.getInstanceCount(clazz, timeout)); + int previous = previousValue.updateAndGet(prev -> prev < 0 ? InstanceCounter.getInstanceCount(clazz, timeout) : prev); System.gc(); - previousCountConsumer.accept(InstanceCounter.getInstanceCount(clazz, timeout)); + previousValue.set(InstanceCounter.getInstanceCount(clazz, timeout)); return String.format("Instances Before GC: %d\nInstances Remaining: %d\nInstances: \n%s\n", - previous, previousCountSupplier.get(), InstanceCounter.getInstances(clazz, timeout).stream() + previous, previousValue.get(), InstanceCounter.getInstances(clazz, timeout).stream() .map(WeakReference::get).filter(Objects::nonNull).map(Object::toString) .collect(Collectors.joining("\n\n"))); } diff --git a/appserver/web/war-util/src/main/java/org/glassfish/web/loader/WebappClassLoader.java b/appserver/web/war-util/src/main/java/org/glassfish/web/loader/WebappClassLoader.java index f71a790c15d..2305e119a6d 100644 --- a/appserver/web/war-util/src/main/java/org/glassfish/web/loader/WebappClassLoader.java +++ b/appserver/web/war-util/src/main/java/org/glassfish/web/loader/WebappClassLoader.java @@ -55,7 +55,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -// Portions Copyright [2016-2020] [Payara Foundation and/or its affiliates] +// Portions Copyright [2016-2021] [Payara Foundation and/or its affiliates] package org.glassfish.web.loader; @@ -405,27 +405,35 @@ public class WebappClassLoader private boolean hotDeploy = false; private final InstanceCounter instanceCounter = new InstanceCounter(this); - private static Class[] CONSTRUCTOR_ARGS_TYPES; - private static Object CONSTRUCTOR_ARGUMENTS; + private static final Class[] CONSTRUCTOR_ARGS_TYPES; + private static final Object CONSTRUCTOR_ARGUMENTS; private static final boolean IS_JDK_VERSION_HIGHER_THAN_8 = JDK.getMajor() > 8; - private static Boolean isMultiReleaseJar; + private static final Boolean isMultiReleaseJar; private static final Name MULTI_RELEASE = new Name("Multi-Release"); static { + Class[] constructorArgsTypes; + Object constructorArguments; if (!IS_JDK_VERSION_HIGHER_THAN_8) { isMultiReleaseJar = false; + constructorArgsTypes = null; + constructorArguments = null; } else { - isMultiReleaseJar = true; + boolean isException = false; try { final Class runtimeVersionClass = Class.forName("java.lang.Runtime$Version"); - CONSTRUCTOR_ARGS_TYPES = new Class[]{File.class, boolean.class, int.class, runtimeVersionClass}; - CONSTRUCTOR_ARGUMENTS = Runtime.class.getDeclaredMethod("version").invoke(null); + constructorArgsTypes = new Class[]{File.class, boolean.class, int.class, runtimeVersionClass}; + constructorArguments = Runtime.class.getDeclaredMethod("version").invoke(null); } catch (Exception e) { - isMultiReleaseJar = false; + isException = true; + constructorArgsTypes = null; + constructorArguments = null; } + isMultiReleaseJar = !isException; } - + CONSTRUCTOR_ARGS_TYPES = constructorArgsTypes; + CONSTRUCTOR_ARGUMENTS = constructorArguments; } // ----------------------------------------------------------- Constructors @@ -1295,7 +1303,7 @@ public Enumeration findResources(String name) throws IOException { logger.log(Level.FINER, " findResources({0})", name); } - List result = new ArrayList(); + List result = new ArrayList<>(); if (repositories != null) { synchronized (jarFilesLock) { @@ -1850,7 +1858,7 @@ public synchronized URL[] getURLs() { try { - ArrayList urls = new ArrayList(); + ArrayList urls = new ArrayList<>(); for (int i = 0; i < length; i++) { if (i < filesLength) { urls.add(i, getURL(files[i])); @@ -1871,9 +1879,8 @@ public synchronized URL[] getURLs() { } - @SuppressWarnings("unchecked") private URL[] removeDuplicate(ArrayList urls) { - HashSet h = new HashSet(urls); + Set h = new HashSet<>(urls); urls.clear(); urls.addAll(h); return urls.toArray(new URL[urls.size()]); diff --git a/nucleus/common/common-util/src/main/java/org/glassfish/common/util/InstanceCounter.java b/nucleus/common/common-util/src/main/java/org/glassfish/common/util/InstanceCounter.java index 9f5739e25c0..df8c6cd6a7d 100644 --- a/nucleus/common/common-util/src/main/java/org/glassfish/common/util/InstanceCounter.java +++ b/nucleus/common/common-util/src/main/java/org/glassfish/common/util/InstanceCounter.java @@ -54,7 +54,7 @@ * Example: Put the following line into the class you want counted: *

* {@code - * private final InstanceCounter instanceCounter = new InstanceCounter<>(this); + * private final InstanceCounter instanceCounter = new InstanceCounter<>(this); * } * * @author Cuba Stanley diff --git a/nucleus/core/kernel/src/main/java/com/sun/enterprise/v3/server/ApplicationLifecycle.java b/nucleus/core/kernel/src/main/java/com/sun/enterprise/v3/server/ApplicationLifecycle.java index 3b1d69e1936..778361b6f97 100644 --- a/nucleus/core/kernel/src/main/java/com/sun/enterprise/v3/server/ApplicationLifecycle.java +++ b/nucleus/core/kernel/src/main/java/com/sun/enterprise/v3/server/ApplicationLifecycle.java @@ -1118,7 +1118,6 @@ public ModuleInfo prepareModule( DeploymentContext context, ProgressTracker tracker) throws Exception { - ActionReport report = context.getActionReport(); List addedEngines = new ArrayList<>(); StructuredDeploymentTracing tracing = StructuredDeploymentTracing.load(context); @@ -1139,6 +1138,7 @@ public ModuleInfo prepareModule( tracker.add(Deployer.class, deployer); } catch(Exception e) { + final ActionReport report = context.getActionReport(); report.failure(logger, "Exception while invoking " + deployer.getClass() + " prepare method", e); throw e; } diff --git a/nucleus/core/logging/src/main/java/com/sun/enterprise/server/logging/GFFileHandler.java b/nucleus/core/logging/src/main/java/com/sun/enterprise/server/logging/GFFileHandler.java index a749f15bce2..828a6e5e468 100644 --- a/nucleus/core/logging/src/main/java/com/sun/enterprise/server/logging/GFFileHandler.java +++ b/nucleus/core/logging/src/main/java/com/sun/enterprise/server/logging/GFFileHandler.java @@ -37,7 +37,7 @@ * only if the new code is made subject to such option by the copyright * holder. */ -// Portions Copyright [2016-2020] [Payara Foundation and/or its affiliates] +// Portions Copyright [2016-2021] [Payara Foundation and/or its affiliates] package com.sun.enterprise.server.logging; @@ -75,13 +75,13 @@ import org.glassfish.config.support.TranslatedConfigView; import org.glassfish.hk2.api.PostConstruct; import org.glassfish.hk2.api.PreDestroy; -import org.glassfish.hk2.api.ServiceLocator; import org.glassfish.server.ServerEnvironmentImpl; import org.jvnet.hk2.annotations.ContractsProvided; import org.jvnet.hk2.annotations.Optional; import org.jvnet.hk2.annotations.Service; import static java.security.AccessController.doPrivileged; +import org.glassfish.internal.api.Globals; /** * GFFileHandler publishes formatted log Messages to a FILE. @@ -115,9 +115,6 @@ public class GFFileHandler extends StreamHandler implements @Inject @Optional private Agent agent; - @Inject - private ServiceLocator habitat; - // This is a OutputStream to keep track of number of bytes // written out to the stream private MeteredStream meter; @@ -495,7 +492,7 @@ protected String evaluateFileName() { } Formatter findFormatterService(String formatterName) { - List formatterServices = habitat.getAllServices(Formatter.class); + List formatterServices = Globals.getDefaultHabitat().getAllServices(Formatter.class); for (Formatter formatter : formatterServices) { if (formatter.getClass().getName().equals(formatterName)) { return formatter; diff --git a/nucleus/deployment/admin/src/main/java/org/glassfish/deployment/admin/DeployCommand.java b/nucleus/deployment/admin/src/main/java/org/glassfish/deployment/admin/DeployCommand.java index 966bcc05f16..42fb958a1b7 100644 --- a/nucleus/deployment/admin/src/main/java/org/glassfish/deployment/admin/DeployCommand.java +++ b/nucleus/deployment/admin/src/main/java/org/glassfish/deployment/admin/DeployCommand.java @@ -176,7 +176,6 @@ public class DeployCommand extends DeployCommandParameters implements AdminComma private ArchiveHandler archiveHandler; private File expansionDir; private ReadableArchive archive; - private ActionReport report; private DeploymentTracing timing; private transient DeployCommandSupplementalInfo suppInfo; private static final String EJB_JAR_XML = "META-INF/ejb-jar.xml"; @@ -213,7 +212,7 @@ public boolean preAuthorization(AdminCommandContext context) { timing = new DeploymentTracing(structuredTracing); - report = context.getActionReport(); + final ActionReport report = context.getActionReport(); logger = context.getLogger(); originalPathValue = path; @@ -403,6 +402,7 @@ public void execute(AdminCommandContext context) { long timeTakenToDeploy = 0; long deploymentTimeMillis = 0; Optional appState = Optional.empty(); + final ActionReport report = context.getActionReport(); try (SpanSequence span = structuredTracing.startSequence(DeploymentTracing.AppStage.VALIDATE_TARGET, "registry")){ if (!hotDeploy) {