From 65889a99973cd5ad4e3299538f39fa5894058b50 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Tue, 7 Jun 2022 14:46:59 +0100 Subject: [PATCH] Reduce memory usage when applying dependency management and exclusions Closes gh-322 --- .../internal/DependencyManagement.java | 18 ++------ ...dencyManagementConfigurationContainer.java | 15 ++++--- .../internal/Exclusions.java | 5 ++- ...dardPomDependencyManagementConfigurer.java | 8 ++-- .../internal/maven/EffectiveModelBuilder.java | 41 +++++++++++++++---- .../internal/maven/MavenPomResolver.java | 26 +++++++----- 6 files changed, 67 insertions(+), 46 deletions(-) diff --git a/src/main/java/io/spring/gradle/dependencymanagement/internal/DependencyManagement.java b/src/main/java/io/spring/gradle/dependencymanagement/internal/DependencyManagement.java index 2041328..7e9e5fa 100644 --- a/src/main/java/io/spring/gradle/dependencymanagement/internal/DependencyManagement.java +++ b/src/main/java/io/spring/gradle/dependencymanagement/internal/DependencyManagement.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2020 the original author or authors. + * Copyright 2014-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -64,8 +64,6 @@ public class DependencyManagement { private final List importedBoms = new ArrayList(); - private List resolvedBoms = new ArrayList(); - DependencyManagement(Project project, PomResolver pomResolver) { this(project, null, pomResolver); } @@ -80,16 +78,6 @@ void importBom(Coordinates coordinates, PropertySource properties) { this.importedBoms.add(new PomReference(coordinates, properties)); } - /** - * Returns the {@link Pom Poms} that have been imported. - * - * @return the imported poms - */ - List getImportedBoms() { - resolveIfNecessary(); - return new ArrayList(this.resolvedBoms); - } - List getImportedBomReferences() { return this.importedBoms; } @@ -180,9 +168,9 @@ private void resolve() { logger.debug("Preserving existing versions: {}", existingVersions); - this.resolvedBoms = this.pomResolver.resolvePoms(this.importedBoms, new ProjectPropertySource(this.project)); + List resolvedBoms = this.pomResolver.resolvePoms(this.importedBoms, new ProjectPropertySource(this.project)); - for (Pom resolvedBom: this.resolvedBoms) { + for (Pom resolvedBom: resolvedBoms) { for (Dependency dependency : resolvedBom.getManagedDependencies()) { if (isEmpty(dependency.getClassifier())) { Coordinates coordinates = dependency.getCoordinates(); diff --git a/src/main/java/io/spring/gradle/dependencymanagement/internal/DependencyManagementConfigurationContainer.java b/src/main/java/io/spring/gradle/dependencymanagement/internal/DependencyManagementConfigurationContainer.java index 38c01a0..91ea104 100644 --- a/src/main/java/io/spring/gradle/dependencymanagement/internal/DependencyManagementConfigurationContainer.java +++ b/src/main/java/io/spring/gradle/dependencymanagement/internal/DependencyManagementConfigurationContainer.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2016 the original author or authors. + * Copyright 2014-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,8 +16,10 @@ package io.spring.gradle.dependencymanagement.internal; +import java.util.ArrayList; +import java.util.List; + import org.gradle.api.Action; -import org.gradle.api.DomainObjectCollection; import org.gradle.api.Project; import org.gradle.api.artifacts.Configuration; import org.gradle.api.artifacts.ConfigurationContainer; @@ -31,7 +33,7 @@ */ public class DependencyManagementConfigurationContainer { - private final DomainObjectCollection configurations; + private final List> actions = new ArrayList>(); private final ConfigurationContainer delegate; @@ -43,7 +45,6 @@ public class DependencyManagementConfigurationContainer { */ public DependencyManagementConfigurationContainer(Project project) { this.delegate = project.getConfigurations(); - this.configurations = project.container(Configuration.class); } /** @@ -70,7 +71,9 @@ Configuration newConfiguration(ConfigurationConfigurer configurer, if (configurer != null) { configurer.configure(configuration); } - this.configurations.add(configuration); + for (Action action: this.actions) { + action.execute(configuration); + } return configuration; } @@ -80,7 +83,7 @@ Configuration newConfiguration(ConfigurationConfigurer configurer, * @param action the action to apply */ public void apply(Action action) { - this.configurations.all(action); + this.actions.add(action); } /** diff --git a/src/main/java/io/spring/gradle/dependencymanagement/internal/Exclusions.java b/src/main/java/io/spring/gradle/dependencymanagement/internal/Exclusions.java index 8288e5b..d004c87 100644 --- a/src/main/java/io/spring/gradle/dependencymanagement/internal/Exclusions.java +++ b/src/main/java/io/spring/gradle/dependencymanagement/internal/Exclusions.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2020 the original author or authors. + * Copyright 2014-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -32,6 +32,9 @@ class Exclusions { private final Map> exclusionsByDependency = new HashMap>(); void add(String dependency, Collection exclusionsForDependency) { + if (exclusionsForDependency.isEmpty()) { + return; + } Set exclusions = this.exclusionsByDependency.get(dependency); if (exclusions == null) { exclusions = new HashSet(); diff --git a/src/main/java/io/spring/gradle/dependencymanagement/internal/StandardPomDependencyManagementConfigurer.java b/src/main/java/io/spring/gradle/dependencymanagement/internal/StandardPomDependencyManagementConfigurer.java index 5c9f095..0d93a65 100644 --- a/src/main/java/io/spring/gradle/dependencymanagement/internal/StandardPomDependencyManagementConfigurer.java +++ b/src/main/java/io/spring/gradle/dependencymanagement/internal/StandardPomDependencyManagementConfigurer.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2020 the original author or authors. + * Copyright 2014-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -140,9 +140,9 @@ private void configureBomImports(Node dependencies) { for (Dependency override: overrides) { appendDependencyNode(dependencies, override.getCoordinates(), override.getScope(), override.getType()); } - List importedBoms = this.dependencyManagement.getImportedBoms(); + List importedBoms = this.dependencyManagement.getImportedBomReferences(); Collections.reverse(importedBoms); - for (Pom resolvedBom: importedBoms) { + for (PomReference resolvedBom: importedBoms) { addImport(dependencies, resolvedBom); } } @@ -175,7 +175,7 @@ private boolean differentVersions(Dependency dependency1, Dependency dependency2 return !version1.equals(version2); } - private void addImport(Node dependencies, Pom importedBom) { + private void addImport(Node dependencies, PomReference importedBom) { appendDependencyNode(dependencies, importedBom.getCoordinates(), "import", "pom"); } diff --git a/src/main/java/io/spring/gradle/dependencymanagement/internal/maven/EffectiveModelBuilder.java b/src/main/java/io/spring/gradle/dependencymanagement/internal/maven/EffectiveModelBuilder.java index 3db9b73..d4a520a 100644 --- a/src/main/java/io/spring/gradle/dependencymanagement/internal/maven/EffectiveModelBuilder.java +++ b/src/main/java/io/spring/gradle/dependencymanagement/internal/maven/EffectiveModelBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2020 the original author or authors. + * Copyright 2014-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -48,8 +48,6 @@ final class EffectiveModelBuilder { private static final Logger logger = LoggerFactory.getLogger(EffectiveModelBuilder.class); - private final ModelCache modelCache = new InMemoryModelCache(); - private final ModelResolver modelResolver; EffectiveModelBuilder(Project project, @@ -57,24 +55,33 @@ final class EffectiveModelBuilder { this.modelResolver = new ConfigurationModelResolver(project, configurationContainer, attributeConfigurer); } - Model buildModel(File pom, PropertySource properties) { + List buildModels(List inputs) { + List models = new ArrayList(); + InMemoryModelCache cache = new InMemoryModelCache(); + for (ModelInput input: inputs) { + models.add(buildModel(input, cache)); + } + return models; + } + + private Model buildModel(ModelInput input, InMemoryModelCache cache) { DefaultModelBuildingRequest request = new DefaultModelBuildingRequest(); request.setSystemProperties(System.getProperties()); - request.setModelSource(new FileModelSource(pom)); + request.setModelSource(new FileModelSource(input.pom)); request.setModelResolver(this.modelResolver); - request.setModelCache(this.modelCache); + request.setModelCache(cache); try { - ModelBuildingResult result = createModelBuilder(properties).build(request); + ModelBuildingResult result = createModelBuilder(input.properties).build(request); List errors = extractErrors(result.getProblems()); if (!errors.isEmpty()) { - reportErrors(errors, pom); + reportErrors(errors, input.pom); } return result.getEffectiveModel(); } catch (ModelBuildingException ex) { logger.debug("Model building failed", ex); - reportErrors(extractErrors(ex.getProblems()), pom); + reportErrors(extractErrors(ex.getProblems()), input.pom); return ex.getResult().getEffectiveModel(); } } @@ -105,6 +112,22 @@ private DefaultModelBuilder createModelBuilder(PropertySource properties) { return modelBuilder; } + /** + * Input to a model building request. + */ + static class ModelInput { + + private final File pom; + + private final PropertySource properties; + + ModelInput(File pom, PropertySource properties) { + this.pom = pom; + this.properties = properties; + } + + } + private static final class InMemoryModelCache implements ModelCache { private final Map cache = new ConcurrentHashMap(); diff --git a/src/main/java/io/spring/gradle/dependencymanagement/internal/maven/MavenPomResolver.java b/src/main/java/io/spring/gradle/dependencymanagement/internal/maven/MavenPomResolver.java index 60b7aeb..23c4785 100644 --- a/src/main/java/io/spring/gradle/dependencymanagement/internal/maven/MavenPomResolver.java +++ b/src/main/java/io/spring/gradle/dependencymanagement/internal/maven/MavenPomResolver.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2020 the original author or authors. + * Copyright 2014-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,7 +16,6 @@ package io.spring.gradle.dependencymanagement.internal.maven; -import java.io.File; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; @@ -36,6 +35,7 @@ import io.spring.gradle.dependencymanagement.internal.DependencyManagementConfigurationContainer; import io.spring.gradle.dependencymanagement.internal.Exclusion; +import io.spring.gradle.dependencymanagement.internal.maven.EffectiveModelBuilder.ModelInput; import io.spring.gradle.dependencymanagement.internal.pom.Coordinates; import io.spring.gradle.dependencymanagement.internal.pom.Dependency; import io.spring.gradle.dependencymanagement.internal.pom.Pom; @@ -120,22 +120,26 @@ private List createPoms(Set resolvedArtifacts, List resolvedPoms = new ArrayList(); + List modelInputs = new ArrayList(); for (ResolvedArtifact resolvedArtifact: resolvedArtifacts) { ModuleVersionIdentifier id = resolvedArtifact.getModuleVersion().getId(); PomReference reference = referencesById.get(createKey(id.getGroup(), id.getName())); CompositePropertySource allProperties = new CompositePropertySource(reference.getProperties(), properties); - resolvedPoms.add(createPom(resolvedArtifact.getFile(), allProperties)); + modelInputs.add(new ModelInput(resolvedArtifact.getFile(), allProperties)); } - return resolvedPoms; + return createPoms(modelInputs); } - private Pom createPom(File file, PropertySource properties) { - Model effectiveModel = this.effectiveModelBuilder.buildModel(file, properties); - Coordinates coordinates = new Coordinates(effectiveModel.getGroupId(), effectiveModel.getArtifactId(), - effectiveModel.getVersion()); - return new Pom(coordinates, getManagedDependencies(effectiveModel), getDependencies(effectiveModel), - asMap(effectiveModel.getProperties())); + private List createPoms(List inputs) { + List effectiveModels = this.effectiveModelBuilder.buildModels(inputs); + List poms = new ArrayList(effectiveModels.size()); + for (Model effectiveModel: effectiveModels) { + Coordinates coordinates = new Coordinates(effectiveModel.getGroupId(), effectiveModel.getArtifactId(), + effectiveModel.getVersion()); + poms.add(new Pom(coordinates, getManagedDependencies(effectiveModel), getDependencies(effectiveModel), + asMap(effectiveModel.getProperties()))); + } + return poms; } private List getManagedDependencies(Model model) {