Skip to content

Commit c927a3c

Browse files
committed
Fix native apps built with GraalVM 25 --future-defaults options
* Added boolean suppliers to customize build steps only when particular future defaults are enabled. * Build time changes help integration tests pass for suites such as `main`, `smallrye-config`, `opentelemetry`, `spring-data-jpa`, `awt`, and multiple security suites.
1 parent 55a8eeb commit c927a3c

File tree

15 files changed

+262
-28
lines changed

15 files changed

+262
-28
lines changed

core/deployment/src/main/java/io/quarkus/deployment/configuration/ConfigMappingUtils.java

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@
2727
import io.quarkus.deployment.builditem.GeneratedClassBuildItem;
2828
import io.quarkus.deployment.builditem.nativeimage.ReflectiveClassBuildItem;
2929
import io.quarkus.deployment.builditem.nativeimage.ReflectiveMethodBuildItem;
30+
import io.quarkus.deployment.pkg.NativeConfig;
31+
import io.quarkus.deployment.pkg.steps.NativeImageFutureDefault;
3032
import io.quarkus.deployment.util.ReflectUtil;
3133
import io.quarkus.hibernate.validator.spi.AdditionalConstrainedClassBuildItem;
3234
import io.smallrye.config.ConfigMapping;
@@ -47,6 +49,7 @@ private ConfigMappingUtils() {
4749

4850
// Used for application Mappings and MP ConfigProperties
4951
public static void processConfigClasses(
52+
NativeConfig nativeConfig,
5053
ConfigurationBuildItem configItem,
5154
CombinedIndexBuildItem combinedIndex,
5255
Map<String, GeneratedClassBuildItem> generatedConfigClasses,
@@ -75,24 +78,28 @@ public static void processConfigClasses(
7578
continue;
7679
}
7780
Kind configClassKind = getConfigClassType(instance);
78-
processConfigClass(configClass, configClassKind, combinedIndex, generatedConfigClasses, reflectiveClasses,
81+
processConfigClass(nativeConfig, configClass, configClassKind, combinedIndex, generatedConfigClasses,
82+
reflectiveClasses,
7983
reflectiveMethods, configClasses, additionalConstrainedClasses);
8084
}
8185
}
8286

8387
public static void processConfigMapping(
88+
NativeConfig nativeConfig,
8489
ConfigurationBuildItem configItem,
8590
CombinedIndexBuildItem combinedIndex,
8691
Map<String, GeneratedClassBuildItem> generatedConfigClasses,
8792
BuildProducer<ReflectiveClassBuildItem> reflectiveClasses,
8893
BuildProducer<ReflectiveMethodBuildItem> reflectiveMethods,
8994
BuildProducer<ConfigClassBuildItem> configClasses,
9095
BuildProducer<AdditionalConstrainedClassBuildItem> additionalConstrainedClasses) {
91-
processConfigClasses(configItem, combinedIndex, generatedConfigClasses, reflectiveClasses, reflectiveMethods,
96+
processConfigClasses(nativeConfig, configItem, combinedIndex, generatedConfigClasses, reflectiveClasses,
97+
reflectiveMethods,
9298
configClasses, additionalConstrainedClasses, CONFIG_MAPPING_NAME);
9399
}
94100

95101
public static void processExtensionConfigMapping(
102+
NativeConfig nativeConfig,
96103
ConfigClass configClass,
97104
CombinedIndexBuildItem combinedIndex,
98105
Map<String, GeneratedClassBuildItem> generatedConfigClasses,
@@ -101,11 +108,12 @@ public static void processExtensionConfigMapping(
101108
BuildProducer<ConfigClassBuildItem> configClasses,
102109
BuildProducer<AdditionalConstrainedClassBuildItem> additionalConstrainedClasses) {
103110

104-
processConfigClass(configClass, Kind.MAPPING, combinedIndex, generatedConfigClasses, reflectiveClasses,
111+
processConfigClass(nativeConfig, configClass, Kind.MAPPING, combinedIndex, generatedConfigClasses, reflectiveClasses,
105112
reflectiveMethods, configClasses, additionalConstrainedClasses);
106113
}
107114

108115
private static void processConfigClass(
116+
NativeConfig nativeConfig,
109117
ConfigClass configClassWithPrefix,
110118
Kind configClassKind,
111119
CombinedIndexBuildItem combinedIndex,
@@ -131,7 +139,11 @@ private static void processConfigClass(
131139
classBytes));
132140
additionalConstrainedClasses.produce(AdditionalConstrainedClassBuildItem.of(mappingMetadata.getClassName(),
133141
classBytes));
134-
reflectiveClasses.produce(ReflectiveClassBuildItem.builder(mappingMetadata.getClassName())
142+
ReflectiveClassBuildItem.Builder reflection = ReflectiveClassBuildItem.builder(mappingMetadata.getClassName());
143+
if (NativeImageFutureDefault.COMPLETE_REFLECTION_TYPES.isEnabled(nativeConfig)) {
144+
reflection.methods();
145+
}
146+
reflectiveClasses.produce(reflection
135147
.reason(ConfigMappingUtils.class.getName())
136148
.build());
137149
reflectiveMethods.produce(new ReflectiveMethodBuildItem(ConfigMappingUtils.class.getName(),

core/deployment/src/main/java/io/quarkus/deployment/pkg/steps/FileSystemResourcesBuildStep.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
import io.quarkus.deployment.builditem.GeneratedFileSystemResourceBuildItem;
1414
import io.quarkus.deployment.builditem.GeneratedFileSystemResourceHandledBuildItem;
1515
import io.quarkus.deployment.builditem.LaunchModeBuildItem;
16+
import io.quarkus.deployment.builditem.nativeimage.ReflectiveClassBuildItem;
17+
import io.quarkus.deployment.builditem.nativeimage.RuntimeInitializedPackageBuildItem;
1618
import io.quarkus.deployment.pkg.builditem.ArtifactResultBuildItem;
1719
import io.quarkus.deployment.pkg.builditem.OutputTargetBuildItem;
1820
import io.quarkus.runtime.LaunchMode;
@@ -30,6 +32,16 @@ public void notNormalMode(OutputTargetBuildItem outputTargetBuildItem,
3032
producer.produce(new GeneratedFileSystemResourceHandledBuildItem());
3133
}
3234

35+
@BuildStep(onlyIf = NativeImageFutureDefault.RunTimeInitializeFileSystemProvider.class)
36+
RuntimeInitializedPackageBuildItem runtimeInitialized() {
37+
return new RuntimeInitializedPackageBuildItem("io.quarkus.fs.util");
38+
}
39+
40+
@BuildStep(onlyIf = NativeImageFutureDefault.RunTimeInitializeFileSystemProvider.class)
41+
ReflectiveClassBuildItem setupReflectionClasses() {
42+
return ReflectiveClassBuildItem.builder("jdk.nio.zipfs.ZipFileSystemProvider").build();
43+
}
44+
3345
@BuildStep(onlyIf = IsProduction.class)
3446
public void normalMode(OutputTargetBuildItem outputTargetBuildItem,
3547
List<GeneratedFileSystemResourceBuildItem> generatedFileSystemResources,

core/deployment/src/main/java/io/quarkus/deployment/pkg/steps/NativeImageBuildStep.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
import io.quarkus.deployment.builditem.nativeimage.NativeImageSecurityProviderBuildItem;
3737
import io.quarkus.deployment.builditem.nativeimage.NativeImageSystemPropertyBuildItem;
3838
import io.quarkus.deployment.builditem.nativeimage.NativeMinimalJavaVersionBuildItem;
39+
import io.quarkus.deployment.builditem.nativeimage.RuntimeInitializedPackageBuildItem;
3940
import io.quarkus.deployment.builditem.nativeimage.UnsupportedOSBuildItem;
4041
import io.quarkus.deployment.pkg.NativeConfig;
4142
import io.quarkus.deployment.pkg.PackageConfig;
@@ -187,6 +188,11 @@ ArtifactResultBuildItem nativeSourcesResult(NativeConfig nativeConfig,
187188
.build());
188189
}
189190

191+
@BuildStep(onlyIf = NativeImageFutureDefault.RunTimeInitializeFileSystemProvider.class)
192+
RuntimeInitializedPackageBuildItem runtimeInitialized() {
193+
return new RuntimeInitializedPackageBuildItem("io.smallrye.common.classloader");
194+
}
195+
190196
@BuildStep
191197
public NativeImageBuildItem build(NativeConfig nativeConfig, LocalesBuildTimeConfig localesBuildTimeConfig,
192198
NativeImageSourceJarBuildItem nativeImageSourceJarBuildItem,
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
package io.quarkus.deployment.pkg.steps;
2+
3+
import java.util.List;
4+
import java.util.Locale;
5+
import java.util.Optional;
6+
import java.util.function.BooleanSupplier;
7+
8+
import io.quarkus.deployment.pkg.NativeConfig;
9+
10+
public enum NativeImageFutureDefault {
11+
COMPLETE_REFLECTION_TYPES,
12+
RUN_TIME_INITIALIZE_FILE_SYSTEM_PROVIDERS,
13+
RUN_TIME_INITIALIZE_SECURITY_PROVIDERS;
14+
15+
private static final String FUTURE_DEFAULTS_MARKER = "--future-defaults=";
16+
17+
public boolean isEnabled(NativeConfig nativeConfig) {
18+
return isFutureDefault(this, nativeConfig);
19+
}
20+
21+
private static boolean isFutureDefault(NativeImageFutureDefault futureDefault, NativeConfig nativeConfig) {
22+
Optional<List<String>>[] additionalBuildArgs = new Optional[] { nativeConfig.additionalBuildArgs(),
23+
nativeConfig.additionalBuildArgsAppend() };
24+
25+
for (Optional<List<String>> args : additionalBuildArgs) {
26+
if (args.isEmpty()) {
27+
continue;
28+
}
29+
List<String> strings = args.get();
30+
for (String buildArg : strings) {
31+
String trimmedBuildArg = buildArg.trim();
32+
if (trimmedBuildArg.contains(FUTURE_DEFAULTS_MARKER)) {
33+
int index = trimmedBuildArg.indexOf('=');
34+
String[] futureDefaultStringArgs = trimmedBuildArg.substring(index + 1).split(",");
35+
for (String futureDefaultString : futureDefaultStringArgs) {
36+
if ("all".equals(futureDefaultString)) {
37+
return true;
38+
}
39+
40+
if ("run-time-initialize-jdk".equals(futureDefaultString)) {
41+
switch (futureDefault) {
42+
case RUN_TIME_INITIALIZE_SECURITY_PROVIDERS:
43+
case RUN_TIME_INITIALIZE_FILE_SYSTEM_PROVIDERS:
44+
return true;
45+
}
46+
}
47+
48+
final NativeImageFutureDefault futureDefaultArg = NativeImageFutureDefault
49+
.valueOf(futureDefaultString.toUpperCase(Locale.ROOT).replace('-', '_'));
50+
if (futureDefaultArg == futureDefault) {
51+
return true;
52+
}
53+
}
54+
}
55+
}
56+
}
57+
58+
return false;
59+
}
60+
61+
private static abstract class AbstractNativeImageFutureDefaultBooleanSupplier implements BooleanSupplier {
62+
protected final NativeConfig nativeConfig;
63+
64+
public AbstractNativeImageFutureDefaultBooleanSupplier(final NativeConfig nativeConfig) {
65+
this.nativeConfig = nativeConfig;
66+
}
67+
}
68+
69+
public static final class RunTimeInitializeFileSystemProvider extends AbstractNativeImageFutureDefaultBooleanSupplier {
70+
public RunTimeInitializeFileSystemProvider(NativeConfig nativeConfig) {
71+
super(nativeConfig);
72+
}
73+
74+
@Override
75+
public boolean getAsBoolean() {
76+
return isFutureDefault(NativeImageFutureDefault.RUN_TIME_INITIALIZE_FILE_SYSTEM_PROVIDERS, nativeConfig);
77+
}
78+
}
79+
80+
public static final class RunTimeInitializeSecurityProvider extends AbstractNativeImageFutureDefaultBooleanSupplier {
81+
public RunTimeInitializeSecurityProvider(NativeConfig nativeConfig) {
82+
super(nativeConfig);
83+
}
84+
85+
@Override
86+
public boolean getAsBoolean() {
87+
return isFutureDefault(NativeImageFutureDefault.RUN_TIME_INITIALIZE_SECURITY_PROVIDERS, nativeConfig);
88+
}
89+
}
90+
91+
public static final class CompleteReflectionTypes extends AbstractNativeImageFutureDefaultBooleanSupplier {
92+
public CompleteReflectionTypes(NativeConfig nativeConfig) {
93+
super(nativeConfig);
94+
}
95+
96+
@Override
97+
public boolean getAsBoolean() {
98+
return isFutureDefault(NativeImageFutureDefault.COMPLETE_REFLECTION_TYPES, nativeConfig);
99+
}
100+
}
101+
}

core/deployment/src/main/java/io/quarkus/deployment/steps/ConfigGenerationBuildStep.java

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@
7373
import io.quarkus.deployment.configuration.RunTimeConfigurationGenerator;
7474
import io.quarkus.deployment.configuration.tracker.ConfigTrackingConfig;
7575
import io.quarkus.deployment.configuration.tracker.ConfigTrackingWriter;
76+
import io.quarkus.deployment.pkg.NativeConfig;
7677
import io.quarkus.deployment.pkg.builditem.ArtifactResultBuildItem;
7778
import io.quarkus.deployment.pkg.builditem.BuildSystemTargetBuildItem;
7879
import io.quarkus.deployment.pkg.steps.NativeOrNativeSourcesBuild;
@@ -197,6 +198,7 @@ void runtimeOverrideConfig(
197198

198199
@BuildStep
199200
void generateMappings(
201+
NativeConfig nativeConfig,
200202
ConfigurationBuildItem configItem,
201203
CombinedIndexBuildItem combinedIndex,
202204
BuildProducer<GeneratedClassBuildItem> generatedClasses,
@@ -207,18 +209,21 @@ void generateMappings(
207209

208210
Map<String, GeneratedClassBuildItem> generatedConfigClasses = new HashMap<>();
209211

210-
processConfigMapping(configItem, combinedIndex, generatedConfigClasses, reflectiveClasses, reflectiveMethods,
212+
processConfigMapping(nativeConfig, configItem, combinedIndex, generatedConfigClasses, reflectiveClasses,
213+
reflectiveMethods,
211214
configClasses, additionalConstrainedClasses);
212215

213216
List<ConfigClass> buildTimeRunTimeMappings = configItem.getReadResult().getBuildTimeRunTimeMappings();
214217
for (ConfigClass buildTimeRunTimeMapping : buildTimeRunTimeMappings) {
215-
processExtensionConfigMapping(buildTimeRunTimeMapping, combinedIndex, generatedConfigClasses, reflectiveClasses,
218+
processExtensionConfigMapping(nativeConfig, buildTimeRunTimeMapping, combinedIndex, generatedConfigClasses,
219+
reflectiveClasses,
216220
reflectiveMethods, configClasses, additionalConstrainedClasses);
217221
}
218222

219223
List<ConfigClass> runTimeMappings = configItem.getReadResult().getRunTimeMappings();
220224
for (ConfigClass runTimeMapping : runTimeMappings) {
221-
processExtensionConfigMapping(runTimeMapping, combinedIndex, generatedConfigClasses, reflectiveClasses,
225+
processExtensionConfigMapping(nativeConfig, runTimeMapping, combinedIndex, generatedConfigClasses,
226+
reflectiveClasses,
222227
reflectiveMethods,
223228
configClasses, additionalConstrainedClasses);
224229
}

0 commit comments

Comments
 (0)