From 1db73a7f9890b10975b90335ca5a51fedbfc220d Mon Sep 17 00:00:00 2001 From: Roberto Cortez Date: Thu, 21 Nov 2024 17:54:23 +0000 Subject: [PATCH] Split creation of the Set to match unknown properties to avoid MethodTooLargeException --- .../quarkus/deployment/ExtensionLoader.java | 2 +- .../BuildTimeConfigurationReader.java | 48 ++++++++++++++--- .../RunTimeConfigurationGenerator.java | 51 +++++++++++-------- .../runtime/configuration/PropertiesUtil.java | 28 ---------- 4 files changed, 72 insertions(+), 57 deletions(-) diff --git a/core/deployment/src/main/java/io/quarkus/deployment/ExtensionLoader.java b/core/deployment/src/main/java/io/quarkus/deployment/ExtensionLoader.java index 963027bc89c1b..a65691e60b8da 100644 --- a/core/deployment/src/main/java/io/quarkus/deployment/ExtensionLoader.java +++ b/core/deployment/src/main/java/io/quarkus/deployment/ExtensionLoader.java @@ -182,7 +182,7 @@ public String getId() { } // ConfigMapping - ConfigClass mapping = readResult.getAllMappings().get(entry.getKey()); + ConfigClass mapping = readResult.getAllMappingsByClass().get(entry.getKey()); if (mapping != null) { mappingClasses.put(entry.getValue(), mapping); continue; diff --git a/core/deployment/src/main/java/io/quarkus/deployment/configuration/BuildTimeConfigurationReader.java b/core/deployment/src/main/java/io/quarkus/deployment/configuration/BuildTimeConfigurationReader.java index b160e70246a94..052ee5e5a0e52 100644 --- a/core/deployment/src/main/java/io/quarkus/deployment/configuration/BuildTimeConfigurationReader.java +++ b/core/deployment/src/main/java/io/quarkus/deployment/configuration/BuildTimeConfigurationReader.java @@ -628,9 +628,9 @@ ReadResult run() { objectsByClass.put(mapping.getKlass(), config.getConfigMapping(mapping.getKlass(), mapping.getPrefix())); } - Set buildTimeNames = getMappingsNames(buildTimeMappings); - Set buildTimeRunTimeNames = getMappingsNames(buildTimeRunTimeMappings); - Set runTimeNames = getMappingsNames(runTimeMappings); + Set buildTimeNames = mappingsToNames(buildTimeMappings).keySet(); + Set buildTimeRunTimeNames = mappingsToNames(buildTimeRunTimeMappings).keySet(); + Set runTimeNames = mappingsToNames(runTimeMappings).keySet(); for (String property : allProperties) { PropertyName name = new PropertyName(property); if (buildTimeNames.contains(name)) { @@ -1222,12 +1222,32 @@ private static void getDefaults( } } - private static Set getMappingsNames(final List configMappings) { + private static Map mappingsToNames(final List configMappings) { Set names = new HashSet<>(); for (ConfigClass configMapping : configMappings) { names.addAll(ConfigMappings.getProperties(configMapping).keySet()); } - return PropertiesUtil.toPropertyNames(names); + Map propertyNames = new HashMap<>(); + for (String name : names) { + PropertyName propertyName = new PropertyName(name); + if (propertyNames.containsKey(propertyName)) { + String existing = propertyNames.remove(propertyName); + if (existing.length() < name.length()) { + propertyNames.put(new PropertyName(existing), existing); + } else if (existing.length() > name.length()) { + propertyNames.put(propertyName, name); + } else { + if (existing.indexOf('*') <= name.indexOf('*')) { + propertyNames.put(new PropertyName(existing), existing); + } else { + propertyNames.put(propertyName, name); + } + } + } else { + propertyNames.put(propertyName, name); + } + } + return propertyNames; } } @@ -1249,7 +1269,9 @@ public static final class ReadResult { final List buildTimeMappings; final List buildTimeRunTimeMappings; final List runTimeMappings; - final Map, ConfigClass> allMappings; + final List allMappings; + final Map, ConfigClass> allMappingsByClass; + final Map allMappingsNames; final Set unknownBuildProperties; final Set deprecatedRuntimeProperties; @@ -1273,7 +1295,9 @@ public ReadResult(final Builder builder) { this.buildTimeMappings = builder.getBuildTimeMappings(); this.buildTimeRunTimeMappings = builder.getBuildTimeRunTimeMappings(); this.runTimeMappings = builder.getRunTimeMappings(); - this.allMappings = mappingsToMap(builder); + this.allMappings = new ArrayList<>(mappingsToMap(builder).values()); + this.allMappingsByClass = mappingsToMap(builder); + this.allMappingsNames = ReadOperation.mappingsToNames(allMappings); this.unknownBuildProperties = builder.getUnknownBuildProperties(); this.deprecatedRuntimeProperties = builder.deprecatedRuntimeProperties; @@ -1355,10 +1379,18 @@ public List getRunTimeMappings() { return runTimeMappings; } - public Map, ConfigClass> getAllMappings() { + public List getAllMappings() { return allMappings; } + public Map, ConfigClass> getAllMappingsByClass() { + return allMappingsByClass; + } + + public Map getAllMappingsNames() { + return allMappingsNames; + } + public Set getUnknownBuildProperties() { return unknownBuildProperties; } diff --git a/core/deployment/src/main/java/io/quarkus/deployment/configuration/RunTimeConfigurationGenerator.java b/core/deployment/src/main/java/io/quarkus/deployment/configuration/RunTimeConfigurationGenerator.java index af52984b99d29..64fa6ac2e57fb 100644 --- a/core/deployment/src/main/java/io/quarkus/deployment/configuration/RunTimeConfigurationGenerator.java +++ b/core/deployment/src/main/java/io/quarkus/deployment/configuration/RunTimeConfigurationGenerator.java @@ -6,6 +6,7 @@ import java.lang.reflect.Field; import java.lang.reflect.Modifier; +import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; @@ -63,6 +64,7 @@ import io.quarkus.runtime.configuration.NameIterator; import io.quarkus.runtime.configuration.PropertiesUtil; import io.quarkus.runtime.configuration.QuarkusConfigFactory; +import io.smallrye.config.ConfigMappingInterface; import io.smallrye.config.ConfigMappings; import io.smallrye.config.ConfigMappings.ConfigClass; import io.smallrye.config.Converters; @@ -88,9 +90,6 @@ public final class RunTimeConfigurationGenerator { public static final MethodDescriptor C_READ_CONFIG = MethodDescriptor.ofMethod(CONFIG_CLASS_NAME, "readConfig", void.class); static final FieldDescriptor C_MAPPED_PROPERTIES = FieldDescriptor.of(CONFIG_CLASS_NAME, "mappedProperties", Set.class); - static final MethodDescriptor C_GENERATE_MAPPED_PROPERTIES = MethodDescriptor.ofMethod(CONFIG_CLASS_NAME, - "generateMappedProperties", Set.class); - static final MethodDescriptor PN_NEW = MethodDescriptor.ofConstructor(PropertyName.class, String.class); static final FieldDescriptor C_UNKNOWN = FieldDescriptor.of(CONFIG_CLASS_NAME, "unknown", Set.class); static final FieldDescriptor C_UNKNOWN_RUNTIME = FieldDescriptor.of(CONFIG_CLASS_NAME, "unknownRuntime", Set.class); @@ -192,9 +191,13 @@ public final class RunTimeConfigurationGenerator { static final MethodDescriptor PU_IS_PROPERTY_IN_ROOTS = MethodDescriptor.ofMethod(PropertiesUtil.class, "isPropertyInRoots", boolean.class, String.class, Set.class); static final MethodDescriptor HS_NEW = MethodDescriptor.ofConstructor(HashSet.class); + static final MethodDescriptor HS_NEW_SIZED = MethodDescriptor.ofConstructor(HashSet.class, int.class); static final MethodDescriptor HS_ADD = MethodDescriptor.ofMethod(HashSet.class, "add", boolean.class, Object.class); + static final MethodDescriptor HS_ADD_ALL = MethodDescriptor.ofMethod(HashSet.class, "addAll", boolean.class, + Collection.class); static final MethodDescriptor HS_CONTAINS = MethodDescriptor.ofMethod(HashSet.class, "contains", boolean.class, Object.class); + static final MethodDescriptor PN_NEW = MethodDescriptor.ofConstructor(PropertyName.class, String.class); // todo: more space-efficient sorted map impl static final MethodDescriptor TM_NEW = MethodDescriptor.ofConstructor(TreeMap.class); @@ -262,7 +265,6 @@ public static final class GenerateOperation implements AutoCloseable { roots = Assert.checkNotNullParam("builder.roots", builder.getBuildTimeReadResult().getAllRoots()); additionalTypes = Assert.checkNotNullParam("additionalTypes", builder.getAdditionalTypes()); cc = ClassCreator.builder().classOutput(classOutput).className(CONFIG_CLASS_NAME).setFinal(true).build(); - generateMappedProperties(); generateEmptyParsers(); // not instantiable try (MethodCreator mc = cc.getMethodCreator(MethodDescriptor.ofConstructor(CONFIG_CLASS_NAME))) { @@ -282,7 +284,8 @@ public static final class GenerateOperation implements AutoCloseable { clinit.setModifiers(Opcodes.ACC_STATIC); cc.getFieldCreator(C_MAPPED_PROPERTIES).setModifiers(Opcodes.ACC_STATIC); - clinit.writeStaticField(C_MAPPED_PROPERTIES, clinit.invokeStaticMethod(C_GENERATE_MAPPED_PROPERTIES)); + clinit.writeStaticField(C_MAPPED_PROPERTIES, clinit.newInstance(HS_NEW_SIZED, + clinit.load((int) ((float) buildTimeConfigResult.getAllMappingsNames().size() / 0.75f + 1.0f)))); cc.getFieldCreator(C_UNKNOWN).setModifiers(Opcodes.ACC_STATIC); clinit.writeStaticField(C_UNKNOWN, clinit.newInstance(HS_NEW)); @@ -290,6 +293,8 @@ public static final class GenerateOperation implements AutoCloseable { cc.getFieldCreator(C_UNKNOWN_RUNTIME).setModifiers(Opcodes.ACC_STATIC); clinit.writeStaticField(C_UNKNOWN_RUNTIME, clinit.newInstance(HS_NEW)); + generateMappedProperties(); + clinitNameBuilder = clinit.newInstance(SB_NEW); // the build time config, which is for user use only (not used by us other than for loading converters) @@ -1191,26 +1196,32 @@ private FieldDescriptor getOrCreateConverterInstance(Field field, ConverterType } private void generateMappedProperties() { - Set names = new HashSet<>(); - for (ConfigClass buildTimeMapping : buildTimeConfigResult.getBuildTimeMappings()) { - names.addAll(ConfigMappings.getProperties(buildTimeMapping).keySet()); - } - for (ConfigClass staticConfigMapping : buildTimeConfigResult.getBuildTimeRunTimeMappings()) { - names.addAll(ConfigMappings.getProperties(staticConfigMapping).keySet()); - } - for (ConfigClass runtimeConfigMapping : buildTimeConfigResult.getRunTimeMappings()) { - names.addAll(ConfigMappings.getProperties(runtimeConfigMapping).keySet()); + MethodDescriptor method = MethodDescriptor.ofMethod(CONFIG_CLASS_NAME, "addMappedProperties", void.class); + MethodCreator mc = cc.getMethodCreator(method); + mc.setModifiers(Opcodes.ACC_PRIVATE | Opcodes.ACC_STATIC); + for (ConfigClass mapping : buildTimeConfigResult.getAllMappings()) { + mc.invokeStaticMethod(generateMappedProperties(mapping, buildTimeConfigResult.getAllMappingsNames())); } - Set propertyNames = PropertiesUtil.toPropertyNames(names); + mc.returnVoid(); + mc.close(); + clinit.invokeStaticMethod(method); + } - MethodCreator mc = cc.getMethodCreator(C_GENERATE_MAPPED_PROPERTIES); + private MethodDescriptor generateMappedProperties(final ConfigClass mapping, + final Map propertyNames) { + MethodDescriptor method = MethodDescriptor.ofMethod(CONFIG_CLASS_NAME, + "addMappedProperties$" + mapping.getKlass().getName().replace('.', '$'), void.class); + MethodCreator mc = cc.getMethodCreator(method); mc.setModifiers(Opcodes.ACC_PRIVATE | Opcodes.ACC_STATIC); - ResultHandle set = mc.newInstance(HS_NEW); - for (PropertyName propertyName : propertyNames) { - mc.invokeVirtualMethod(HS_ADD, set, mc.newInstance(PN_NEW, mc.load(propertyName.getName()))); + Map properties = ConfigMappings.getProperties(mapping); + ResultHandle set = mc.readStaticField(C_MAPPED_PROPERTIES); + for (String propertyName : properties.keySet()) { + String name = propertyNames.get(new PropertyName(propertyName)); + mc.invokeVirtualMethod(HS_ADD, set, mc.newInstance(PN_NEW, mc.load(name))); } - mc.returnValue(set); + mc.returnVoid(); mc.close(); + return method; } private void reportUnknown(BytecodeCreator bc, ResultHandle unknownProperty) { diff --git a/core/runtime/src/main/java/io/quarkus/runtime/configuration/PropertiesUtil.java b/core/runtime/src/main/java/io/quarkus/runtime/configuration/PropertiesUtil.java index 18978d1714028..7c51a8707538e 100644 --- a/core/runtime/src/main/java/io/quarkus/runtime/configuration/PropertiesUtil.java +++ b/core/runtime/src/main/java/io/quarkus/runtime/configuration/PropertiesUtil.java @@ -1,11 +1,7 @@ package io.quarkus.runtime.configuration; -import java.util.HashMap; -import java.util.Map; import java.util.Set; -import io.smallrye.config.PropertyName; - public class PropertiesUtil { private PropertiesUtil() { throw new IllegalStateException("Utility class"); @@ -48,28 +44,4 @@ public static boolean isPropertyInRoot(final String property, final String root) public static boolean isPropertyQuarkusCompoundName(NameIterator propertyName) { return propertyName.getName().startsWith("\"quarkus."); } - - public static Set toPropertyNames(final Set names) { - Map propertyNames = new HashMap<>(); - for (String name : names) { - PropertyName propertyName = new PropertyName(name); - if (propertyNames.containsKey(propertyName)) { - String existing = propertyNames.remove(propertyName); - if (existing.length() < name.length()) { - propertyNames.put(new PropertyName(existing), existing); - } else if (existing.length() > name.length()) { - propertyNames.put(propertyName, name); - } else { - if (existing.indexOf('*') <= name.indexOf('*')) { - propertyNames.put(new PropertyName(existing), existing); - } else { - propertyNames.put(propertyName, name); - } - } - } else { - propertyNames.put(propertyName, name); - } - } - return propertyNames.keySet(); - } }