From d95a3ef74d7e676a57f7e133f94e760aad63dcbd Mon Sep 17 00:00:00 2001 From: Gaurav Gupta Date: Mon, 1 Aug 2022 15:25:28 +0530 Subject: [PATCH] FISH-5723 Fixes WebappClassloader memory-leak issue by removing JAXRSResources classes from cache on shutdown event (#5102) * FISH-5723 Fixes WebappClassloader memory-leak issue by removing JAXRS Resources classes from cache on shutdown event Signed-off-by: Gaurav Gupta --- .../jersey/internal/util/collection/Cache.java | 13 ++++++++++++- .../ext/cdi1x/internal/CdiComponentProvider.java | 11 ++++++++++- ...diComponentProviderClientRuntimeSpecifics.java | 9 ++++++++- .../CdiComponentProviderRuntimeSpecifics.java | 5 ++++- ...diComponentProviderServerRuntimeSpecifics.java | 15 ++++++++++++++- 5 files changed, 48 insertions(+), 5 deletions(-) diff --git a/core-common/src/main/java/org/glassfish/jersey/internal/util/collection/Cache.java b/core-common/src/main/java/org/glassfish/jersey/internal/util/collection/Cache.java index 923552cbb4..40d94abe26 100644 --- a/core-common/src/main/java/org/glassfish/jersey/internal/util/collection/Cache.java +++ b/core-common/src/main/java/org/glassfish/jersey/internal/util/collection/Cache.java @@ -1,5 +1,6 @@ /* - * Copyright (c) 2017, 2019 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2022 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022 Payara Foundation and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0, which is available at @@ -16,6 +17,7 @@ package org.glassfish.jersey.internal.util.collection; +import java.util.Enumeration; import java.util.concurrent.Callable; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ExecutionException; @@ -107,6 +109,15 @@ public void clear() { cache.clear(); } + /** + * Get the cache keys + * + * @return + */ + public Enumeration keys() { + return cache.keys(); + } + /** * Returns true if the key has already been cached. * diff --git a/ext/cdi/jersey-cdi1x/src/main/java/org/glassfish/jersey/ext/cdi1x/internal/CdiComponentProvider.java b/ext/cdi/jersey-cdi1x/src/main/java/org/glassfish/jersey/ext/cdi1x/internal/CdiComponentProvider.java index 7488e5152d..6ff37b4c94 100644 --- a/ext/cdi/jersey-cdi1x/src/main/java/org/glassfish/jersey/ext/cdi1x/internal/CdiComponentProvider.java +++ b/ext/cdi/jersey-cdi1x/src/main/java/org/glassfish/jersey/ext/cdi1x/internal/CdiComponentProvider.java @@ -1,6 +1,6 @@ /* * Copyright (c) 2013, 2022 Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2018 Payara Foundation and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2022 Payara Foundation and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0, which is available at @@ -59,12 +59,16 @@ import javax.enterprise.inject.spi.AnnotatedParameter; import javax.enterprise.inject.spi.AnnotatedType; import javax.enterprise.inject.spi.Bean; +import javax.enterprise.inject.spi.BeanManager; +import javax.enterprise.inject.spi.BeforeBeanDiscovery; +import javax.enterprise.inject.spi.BeforeShutdown; import javax.enterprise.inject.spi.Extension; import javax.enterprise.inject.spi.InjectionPoint; import javax.enterprise.inject.spi.InjectionTarget; import javax.enterprise.inject.spi.ProcessAnnotatedType; import javax.enterprise.inject.spi.ProcessInjectionTarget; import javax.enterprise.util.AnnotationLiteral; +import javax.inject.Qualifier; import org.glassfish.jersey.ext.cdi1x.internal.spi.InjectionManagerInjectedTarget; import org.glassfish.jersey.ext.cdi1x.internal.spi.InjectionManagerStore; @@ -857,6 +861,11 @@ private void beforeBeanDiscovery(@Observes final BeforeBeanDiscovery beforeBeanD ); } + @SuppressWarnings("unused") + private void beforeShutDown(@Observes final BeforeShutdown beforeShutdown, final BeanManager beanManager) { + runtimeSpecifics.clearJaxRsResource(Thread.currentThread().getContextClassLoader()); + } + /** * Add a predicate to test HK2 dependency to create a CDI bridge bean to HK2 for it. * @param predicate to test whether given class is a HK2 dependency. diff --git a/ext/cdi/jersey-cdi1x/src/main/java/org/glassfish/jersey/ext/cdi1x/internal/CdiComponentProviderClientRuntimeSpecifics.java b/ext/cdi/jersey-cdi1x/src/main/java/org/glassfish/jersey/ext/cdi1x/internal/CdiComponentProviderClientRuntimeSpecifics.java index 7aa34a8b82..00d7ae57a2 100644 --- a/ext/cdi/jersey-cdi1x/src/main/java/org/glassfish/jersey/ext/cdi1x/internal/CdiComponentProviderClientRuntimeSpecifics.java +++ b/ext/cdi/jersey-cdi1x/src/main/java/org/glassfish/jersey/ext/cdi1x/internal/CdiComponentProviderClientRuntimeSpecifics.java @@ -1,5 +1,6 @@ /* - * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2022 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022 Payara Foundation and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0, which is available at @@ -20,6 +21,7 @@ import javax.enterprise.inject.spi.AnnotatedType; import javax.ws.rs.core.Context; import java.lang.annotation.Annotation; +import java.util.Enumeration; import java.util.HashSet; import java.util.Set; @@ -59,4 +61,9 @@ public boolean isAcceptableResource(Class resource) { public boolean isJaxRsResource(Class resource) { return false; } + + @Override + public void clearJaxRsResource(ClassLoader loader) { + } + } diff --git a/ext/cdi/jersey-cdi1x/src/main/java/org/glassfish/jersey/ext/cdi1x/internal/CdiComponentProviderRuntimeSpecifics.java b/ext/cdi/jersey-cdi1x/src/main/java/org/glassfish/jersey/ext/cdi1x/internal/CdiComponentProviderRuntimeSpecifics.java index 35ab06f692..d8681f2fff 100644 --- a/ext/cdi/jersey-cdi1x/src/main/java/org/glassfish/jersey/ext/cdi1x/internal/CdiComponentProviderRuntimeSpecifics.java +++ b/ext/cdi/jersey-cdi1x/src/main/java/org/glassfish/jersey/ext/cdi1x/internal/CdiComponentProviderRuntimeSpecifics.java @@ -1,5 +1,6 @@ /* - * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2022 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022 Payara Foundation and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0, which is available at @@ -34,4 +35,6 @@ interface CdiComponentProviderRuntimeSpecifics { boolean isAcceptableResource(Class resource); boolean isJaxRsResource(Class resource); + + void clearJaxRsResource(ClassLoader loader); } diff --git a/ext/cdi/jersey-cdi1x/src/main/java/org/glassfish/jersey/ext/cdi1x/internal/CdiComponentProviderServerRuntimeSpecifics.java b/ext/cdi/jersey-cdi1x/src/main/java/org/glassfish/jersey/ext/cdi1x/internal/CdiComponentProviderServerRuntimeSpecifics.java index bfa53a36f9..ee9ca27f80 100644 --- a/ext/cdi/jersey-cdi1x/src/main/java/org/glassfish/jersey/ext/cdi1x/internal/CdiComponentProviderServerRuntimeSpecifics.java +++ b/ext/cdi/jersey-cdi1x/src/main/java/org/glassfish/jersey/ext/cdi1x/internal/CdiComponentProviderServerRuntimeSpecifics.java @@ -1,5 +1,6 @@ /* - * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2022 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022 Payara Foundation and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0, which is available at @@ -48,6 +49,7 @@ import static java.lang.annotation.ElementType.PARAMETER; import static java.lang.annotation.ElementType.TYPE; import static java.lang.annotation.RetentionPolicy.RUNTIME; +import java.util.Enumeration; /** * Server side runtime CDI ComponentProvider specific implementation. @@ -225,6 +227,17 @@ public boolean isJaxRsResource(Class resource) { return jaxRsResourceCache.apply(resource); } + @Override + public void clearJaxRsResource(ClassLoader loader) { + Enumeration> keys = jaxRsResourceCache.keys(); + while (keys.hasMoreElements()) { + Class key = keys.nextElement(); + if (key.getClassLoader() == loader) { + jaxRsResourceCache.remove(key); + } + } + } + @Override public boolean containsJaxRsParameterizedCtor(final AnnotatedType annotatedType) { return CdiComponentProvider