Skip to content

Commit d119e76

Browse files
authored
Merge pull request #51712 from gsmet/jackson-leak
Fix two class loader-related leaks, one in Jackson, the other in QuarkusClassLoader
2 parents a38a111 + 5bd70d1 commit d119e76

File tree

4 files changed

+53
-39
lines changed

4 files changed

+53
-39
lines changed

extensions/jackson/deployment/src/main/java/io/quarkus/jackson/deployment/JacksonProcessor.java

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@
5656
import io.quarkus.deployment.annotations.ExecutionTime;
5757
import io.quarkus.deployment.annotations.Record;
5858
import io.quarkus.deployment.builditem.CombinedIndexBuildItem;
59+
import io.quarkus.deployment.builditem.ShutdownListenerBuildItem;
5960
import io.quarkus.deployment.builditem.nativeimage.ReflectiveClassBuildItem;
6061
import io.quarkus.deployment.builditem.nativeimage.ReflectiveHierarchyBuildItem;
6162
import io.quarkus.deployment.builditem.nativeimage.ReflectiveMethodBuildItem;
@@ -73,9 +74,8 @@
7374
import io.quarkus.jackson.ObjectMapperCustomizer;
7475
import io.quarkus.jackson.runtime.ConfigurationCustomizer;
7576
import io.quarkus.jackson.runtime.JacksonBuildTimeConfig;
77+
import io.quarkus.jackson.runtime.JacksonRecorder;
7678
import io.quarkus.jackson.runtime.JacksonSupport;
77-
import io.quarkus.jackson.runtime.JacksonSupportRecorder;
78-
import io.quarkus.jackson.runtime.MixinsRecorder;
7979
import io.quarkus.jackson.runtime.ObjectMapperProducer;
8080
import io.quarkus.jackson.runtime.VertxHybridPoolObjectMapperCustomizer;
8181
import io.quarkus.jackson.spi.ClassPathJacksonModuleBuildItem;
@@ -474,7 +474,7 @@ void generateCustomizer(BuildProducer<GeneratedBeanBuildItem> generatedBeans,
474474

475475
@Record(ExecutionTime.STATIC_INIT)
476476
@BuildStep
477-
public void supportMixins(MixinsRecorder recorder,
477+
public void supportMixins(JacksonRecorder recorder,
478478
CombinedIndexBuildItem combinedIndexBuildItem,
479479
BuildProducer<SyntheticBeanBuildItem> syntheticBeans,
480480
BuildProducer<ReflectiveClassBuildItem> reflectiveClass) {
@@ -523,7 +523,7 @@ public void supportMixins(MixinsRecorder recorder,
523523

524524
@Record(ExecutionTime.STATIC_INIT)
525525
@BuildStep
526-
public SyntheticBeanBuildItem jacksonSupport(JacksonSupportRecorder recorder,
526+
public SyntheticBeanBuildItem jacksonSupport(JacksonRecorder recorder,
527527
JacksonBuildTimeConfig jacksonBuildTimeConfig) {
528528
return SyntheticBeanBuildItem
529529
.configure(JacksonSupport.class)
@@ -532,6 +532,12 @@ public SyntheticBeanBuildItem jacksonSupport(JacksonSupportRecorder recorder,
532532
.done();
533533
}
534534

535+
@Record(ExecutionTime.RUNTIME_INIT)
536+
@BuildStep
537+
public ShutdownListenerBuildItem clearCachesOnShutdown(JacksonRecorder recorder) {
538+
return new ShutdownListenerBuildItem(recorder.clearCachesOnShutdown());
539+
}
540+
535541
private Optional<String> determinePropertyNamingStrategyClassName(JacksonBuildTimeConfig jacksonBuildTimeConfig) {
536542
if (jacksonBuildTimeConfig.propertyNamingStrategy().isEmpty()) {
537543
return Optional.empty();

extensions/jackson/runtime/src/main/java/io/quarkus/jackson/runtime/JacksonSupportRecorder.java renamed to extensions/jackson/runtime/src/main/java/io/quarkus/jackson/runtime/JacksonRecorder.java

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,23 @@
11
package io.quarkus.jackson.runtime;
22

3+
import java.util.Map;
34
import java.util.Optional;
45
import java.util.function.Supplier;
56

7+
import com.fasterxml.jackson.databind.ObjectMapper;
68
import com.fasterxml.jackson.databind.PropertyNamingStrategies;
9+
import com.fasterxml.jackson.databind.type.TypeFactory;
710

11+
import io.quarkus.jackson.ObjectMapperCustomizer;
812
import io.quarkus.runtime.annotations.Recorder;
13+
import io.quarkus.runtime.annotations.RuntimeInit;
14+
import io.quarkus.runtime.annotations.StaticInit;
15+
import io.quarkus.runtime.shutdown.ShutdownListener;
916

1017
@Recorder
11-
public class JacksonSupportRecorder {
18+
public class JacksonRecorder {
1219

20+
@StaticInit
1321
public Supplier<JacksonSupport> supplier(Optional<String> propertyNamingStrategyClassName) {
1422
return new Supplier<>() {
1523
@Override
@@ -36,4 +44,36 @@ public Optional<PropertyNamingStrategies.NamingBase> configuredNamingStrategy()
3644
}
3745
};
3846
}
47+
48+
@StaticInit
49+
public Supplier<ObjectMapperCustomizer> customizerSupplier(Map<Class<?>, Class<?>> mixinsMap) {
50+
return new Supplier<>() {
51+
@Override
52+
public ObjectMapperCustomizer get() {
53+
return new ObjectMapperCustomizer() {
54+
@Override
55+
public void customize(ObjectMapper objectMapper) {
56+
for (var entry : mixinsMap.entrySet()) {
57+
objectMapper.addMixIn(entry.getKey(), entry.getValue());
58+
}
59+
}
60+
61+
@Override
62+
public int priority() {
63+
return DEFAULT_PRIORITY + 1;
64+
}
65+
};
66+
}
67+
};
68+
}
69+
70+
@RuntimeInit
71+
public ShutdownListener clearCachesOnShutdown() {
72+
return new ShutdownListener() {
73+
@Override
74+
public void shutdown(ShutdownNotification notification) {
75+
TypeFactory.defaultInstance().clearCache();
76+
}
77+
};
78+
}
3979
}

extensions/jackson/runtime/src/main/java/io/quarkus/jackson/runtime/MixinsRecorder.java

Lines changed: 0 additions & 34 deletions
This file was deleted.

independent-projects/bootstrap/core/src/main/java/io/quarkus/bootstrap/classloading/QuarkusClassLoader.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,8 @@ public void reset(Map<String, byte[]> generatedResources, Map<String, byte[]> tr
233233
throw new IllegalStateException("Classloader is not resettable");
234234
}
235235
synchronized (this) {
236+
// we don't want the previous MemoryClassPathElement to leak as a key of protectionDomains
237+
protectionDomains.remove(this.transformedClasses);
236238
this.transformedClasses = new MemoryClassPathElement(transformedClasses, true);
237239
resettableElement.reset(generatedResources);
238240
classPathResourceIndex = null;

0 commit comments

Comments
 (0)