Skip to content

Commit abc1684

Browse files
committed
[GR-49996] Make -jar only implicitly set image name if not already defined previously.
PullRequest: graal/16638
2 parents 7507423 + a5b2ec7 commit abc1684

File tree

4 files changed

+48
-20
lines changed

4 files changed

+48
-20
lines changed

docs/reference-manual/native-image/guides/build-native-executable-from-jar.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,8 @@ For other installation options, visit the [Downloads section](https://www.graalv
7272
```
7373
7474
It will produce a native executable in the project root directory.
75+
The default name of the image will be the name of the JAR file (`App` in this case).
76+
It can be customized by either providing a custom name as a last argument (for example, `native-image -jar App.jar imagename`), or by using `-o imagename` before or after `-jar jarfile`, for example: `native-image -jar App.jar -o imagename`.
7577
7678
6. Run the native executable:
7779
```shell

substratevm/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ This changelog summarizes major changes to GraalVM Native Image.
44

55
## GraalVM for JDK 23 (Internal Version 24.1.0)
66
* (GR-51106) Fields that are accessed via a `VarHandle` or `MethodHandle` are no longer marked as "unsafe accessed" when the `VarHandle`/`MethodHandle` can be fully intrinsified.
7+
* (GR-49996) Ensure explicitly set image name (e.g., via `-o imagename`) is not accidentally overwritten by `-jar jarfile` option.
78

89
## GraalVM for JDK 22 (Internal Version 24.0.0)
910
* (GR-48304) Red Hat added support for the JFR event ThreadAllocationStatistics.

substratevm/src/com.oracle.svm.driver/src/com/oracle/svm/driver/DefaultOptionHandler.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,7 @@ private void handleJarFileArg(Path jarFilePath) {
251251
}
252252
if (!jarFileNameBase.isEmpty()) {
253253
String origin = "manifest from " + jarFilePath.toUri();
254-
nativeImage.addPlainImageBuilderArg(nativeImage.oHName + jarFileNameBase, origin);
254+
nativeImage.addPlainImageBuilderArg(nativeImage.oHName + jarFileNameBase, origin, false);
255255
}
256256
Path finalFilePath = nativeImage.useBundle() ? nativeImage.bundleSupport.substituteClassPath(jarFilePath) : jarFilePath;
257257
if (!NativeImage.processJarManifestMainAttributes(finalFilePath, nativeImage::handleManifestFileAttributes)) {

substratevm/src/com.oracle.svm.driver/src/com/oracle/svm/driver/NativeImage.java

Lines changed: 44 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1091,7 +1091,7 @@ private int completeImageBuild() {
10911091
addTargetArguments();
10921092

10931093
String defaultLibC = OS.getCurrent() == OS.LINUX ? "glibc" : null;
1094-
targetLibC = getHostedOptionFinalArgument(imageBuilderArgs, oHUseLibC).map(ArgumentEntry::value).orElse(System.getProperty("substratevm.HostLibC", defaultLibC));
1094+
targetLibC = getHostedOptionArgument(imageBuilderArgs, oHUseLibC).map(ArgumentEntry::value).orElse(System.getProperty("substratevm.HostLibC", defaultLibC));
10951095

10961096
String clibrariesBuilderArg = config.getBuilderCLibrariesPaths().stream()
10971097
.flatMap(this::resolveTargetSpecificPaths)
@@ -1166,7 +1166,7 @@ private int completeImageBuild() {
11661166

11671167
imageBuilderJavaArgs.addAll(getAgentArguments());
11681168

1169-
mainClass = getHostedOptionFinalArgumentValue(imageBuilderArgs, oHClass);
1169+
mainClass = getHostedOptionArgumentValue(imageBuilderArgs, oHClass);
11701170
buildExecutable = imageBuilderArgs.stream().noneMatch(arg -> arg.startsWith(oHEnableSharedLibraryFlagPrefix));
11711171
staticExecutable = imageBuilderArgs.stream().anyMatch(arg -> arg.contains(oHEnableStaticExecutable));
11721172
boolean listModules = imageBuilderArgs.stream().anyMatch(arg -> arg.contains(oH + "+" + "ListModules"));
@@ -1188,8 +1188,8 @@ private int completeImageBuild() {
11881188

11891189
if (!jarOptionMode) {
11901190
/* Main-class from customImageBuilderArgs counts as explicitMainClass */
1191-
boolean explicitMainClass = getHostedOptionFinalArgumentValue(imageBuilderArgs, oHClass) != null;
1192-
mainClassModule = getHostedOptionFinalArgumentValue(imageBuilderArgs, oHModule);
1191+
boolean explicitMainClass = getHostedOptionArgumentValue(imageBuilderArgs, oHClass) != null;
1192+
mainClassModule = getHostedOptionArgumentValue(imageBuilderArgs, oHModule);
11931193

11941194
boolean hasMainClassModule = mainClassModule != null && !mainClassModule.isEmpty();
11951195
boolean hasMainClass = mainClass != null && !mainClass.isEmpty();
@@ -1207,11 +1207,11 @@ private int completeImageBuild() {
12071207

12081208
if (extraImageArgs.isEmpty()) {
12091209
/* No explicit image name, define image name by other means */
1210-
if (getHostedOptionFinalArgumentValue(imageBuilderArgs, oHName) == null) {
1210+
if (getHostedOptionArgumentValue(imageBuilderArgs, oHName) == null) {
12111211
/* Also no explicit image name given as customImageBuilderArgs */
12121212
if (explicitMainClass) {
12131213
imageBuilderArgs.add(oH(SubstrateOptions.Name, "main-class lower case as image name") + mainClass.toLowerCase());
1214-
} else if (getHostedOptionFinalArgumentValue(imageBuilderArgs, oHName) == null) {
1214+
} else if (getHostedOptionArgumentValue(imageBuilderArgs, oHName) == null) {
12151215
if (hasMainClassModule) {
12161216
imageBuilderArgs.add(oH(SubstrateOptions.Name, "image-name from module-name") + mainClassModule.toLowerCase());
12171217
} else if (!listModules) {
@@ -1236,9 +1236,9 @@ private int completeImageBuild() {
12361236
}
12371237
}
12381238

1239-
ArgumentEntry imageNameEntry = getHostedOptionFinalArgument(imageBuilderArgs, oHName).orElseThrow();
1239+
ArgumentEntry imageNameEntry = getHostedOptionArgument(imageBuilderArgs, oHName).orElseThrow();
12401240
imageName = imageNameEntry.value;
1241-
ArgumentEntry imagePathEntry = getHostedOptionFinalArgument(imageBuilderArgs, oHPath).orElseThrow();
1241+
ArgumentEntry imagePathEntry = getHostedOptionArgument(imageBuilderArgs, oHPath).orElseThrow();
12421242
imagePath = Path.of(imagePathEntry.value);
12431243
Path imageNamePath = Path.of(imageName);
12441244
Path imageNamePathParent = imageNamePath.getParent();
@@ -1307,7 +1307,7 @@ private int completeImageBuild() {
13071307
imageProvidedJars.forEach(this::processClasspathNativeImageMetaInf);
13081308

13091309
if (!config.buildFallbackImage()) {
1310-
Optional<ArgumentEntry> fallbackThresholdEntry = getHostedOptionFinalArgument(imageBuilderArgs, oHFallbackThreshold);
1310+
Optional<ArgumentEntry> fallbackThresholdEntry = getHostedOptionArgument(imageBuilderArgs, oHFallbackThreshold);
13111311
if (fallbackThresholdEntry.isPresent() && fallbackThresholdEntry.get().value.equals("" + SubstrateOptions.ForceFallback)) {
13121312
/* Bypass regular build and proceed with fallback image building */
13131313
return ExitStatus.FALLBACK_IMAGE.getValue();
@@ -1344,11 +1344,11 @@ private static String getLocationAgnosticArgPrefix(String argPrefix) {
13441344
return "^" + argPrefix.substring(0, argPrefix.length() - 1) + "(@[^=]*)?=";
13451345
}
13461346

1347-
private static String getHostedOptionFinalArgumentValue(List<String> args, String argPrefix) {
1348-
return getHostedOptionFinalArgument(args, argPrefix).map(entry -> entry.value).orElse(null);
1347+
private static String getHostedOptionArgumentValue(List<String> args, String argPrefix) {
1348+
return getHostedOptionArgument(args, argPrefix).map(entry -> entry.value).orElse(null);
13491349
}
13501350

1351-
private static Optional<ArgumentEntry> getHostedOptionFinalArgument(List<String> args, String argPrefix) {
1351+
private static Optional<ArgumentEntry> getHostedOptionArgument(List<String> args, String argPrefix) {
13521352
List<ArgumentEntry> values = getHostedOptionArgumentValues(args, argPrefix);
13531353
return values.isEmpty() ? Optional.empty() : Optional.of(values.get(values.size() - 1));
13541354
}
@@ -1371,7 +1371,7 @@ private static List<ArgumentEntry> getHostedOptionArgumentValues(List<String> ar
13711371
private record ArgumentEntry(int index, String value) {
13721372
}
13731373

1374-
private static Boolean getHostedOptionFinalBooleanArgumentValue(List<String> args, OptionKey<Boolean> option) {
1374+
private static Boolean getHostedOptionBooleanArgumentValue(List<String> args, OptionKey<Boolean> option) {
13751375
String locationAgnosticBooleanPattern = "^" + oH + "[+-]" + option.getName() + "(@[^=]*)?$";
13761376
Pattern pattern = Pattern.compile(locationAgnosticBooleanPattern);
13771377
Boolean result = null;
@@ -1442,7 +1442,7 @@ private void addTargetArguments() {
14421442
* process (see comments for NativeImageGenerator.getTargetPlatform), we are parsing the
14431443
* --target argument here, and generating required internal arguments.
14441444
*/
1445-
targetPlatform = getHostedOptionFinalArgumentValue(imageBuilderArgs, oHTargetPlatform);
1445+
targetPlatform = getHostedOptionArgumentValue(imageBuilderArgs, oHTargetPlatform);
14461446
if (targetPlatform == null) {
14471447
return;
14481448
}
@@ -2007,11 +2007,36 @@ List<String> apply(boolean strict) {
20072007
}
20082008

20092009
void addPlainImageBuilderArg(String plainArg, String origin) {
2010-
addPlainImageBuilderArg(injectHostedOptionOrigin(plainArg, origin));
2010+
addPlainImageBuilderArg(plainArg, origin, true);
2011+
}
2012+
2013+
void addPlainImageBuilderArg(String plainArg, String origin, boolean override) {
2014+
addPlainImageBuilderArg(injectHostedOptionOrigin(plainArg, origin), override);
20112015
}
20122016

20132017
void addPlainImageBuilderArg(String plainArg) {
2018+
addPlainImageBuilderArg(plainArg, true);
2019+
}
2020+
2021+
void addPlainImageBuilderArg(String plainArg, boolean override) {
20142022
assert plainArg.startsWith(NativeImage.oH) || plainArg.startsWith(NativeImage.oR);
2023+
if (!override) {
2024+
int posValueSeparator = plainArg.indexOf('=');
2025+
if (posValueSeparator > 0) {
2026+
String argPrefix = plainArg.substring(0, posValueSeparator);
2027+
int posOriginSeparator = plainArg.indexOf('@');
2028+
if (posOriginSeparator > 0) {
2029+
argPrefix = argPrefix.substring(0, posOriginSeparator);
2030+
}
2031+
String existingValue = getHostedOptionArgumentValue(imageBuilderArgs, argPrefix + '=');
2032+
if (existingValue != null) {
2033+
/* Respect the existing value. Do not append overriding value. */
2034+
return;
2035+
}
2036+
} else {
2037+
VMError.shouldNotReachHere("override=false currently only works for non-boolean options");
2038+
}
2039+
}
20152040
imageBuilderArgs.add(plainArg);
20162041
}
20172042

@@ -2344,7 +2369,7 @@ private static boolean logRedirectedToFile() {
23442369

23452370
private boolean configureBuildOutput() {
23462371
boolean useColorfulOutput = false;
2347-
String colorValue = getHostedOptionFinalArgumentValue(imageBuilderArgs, oHColor);
2372+
String colorValue = getHostedOptionArgumentValue(imageBuilderArgs, oHColor);
23482373
if (colorValue != null) { // use value set by user
23492374
if ("always".equals(colorValue)) {
23502375
useColorfulOutput = true;
@@ -2353,18 +2378,18 @@ private boolean configureBuildOutput() {
23532378
addPlainImageBuilderArg(oHColor + (useColorfulOutput ? "always" : "never"), OptionOrigin.originDriver);
23542379
}
23552380
} else {
2356-
Boolean buildOutputColorfulValue = getHostedOptionFinalBooleanArgumentValue(imageBuilderArgs, SubstrateOptions.BuildOutputColorful);
2381+
Boolean buildOutputColorfulValue = getHostedOptionBooleanArgumentValue(imageBuilderArgs, SubstrateOptions.BuildOutputColorful);
23572382
if (buildOutputColorfulValue != null) {
23582383
useColorfulOutput = buildOutputColorfulValue; // use value set by user
23592384
} else if (hasColorSupport()) {
23602385
useColorfulOutput = true;
23612386
addPlainImageBuilderArg(oHColor + "always", OptionOrigin.originDriver);
23622387
}
23632388
}
2364-
if (getHostedOptionFinalBooleanArgumentValue(imageBuilderArgs, SubstrateOptions.BuildOutputProgress) == null && hasProgressSupport(imageBuilderArgs)) {
2389+
if (getHostedOptionBooleanArgumentValue(imageBuilderArgs, SubstrateOptions.BuildOutputProgress) == null && hasProgressSupport(imageBuilderArgs)) {
23652390
addPlainImageBuilderArg(oHEnableBuildOutputProgress);
23662391
}
2367-
if (getHostedOptionFinalBooleanArgumentValue(imageBuilderArgs, SubstrateOptions.BuildOutputLinks) == null && (colorValue == null || "auto".equals(colorValue)) && useColorfulOutput) {
2392+
if (getHostedOptionBooleanArgumentValue(imageBuilderArgs, SubstrateOptions.BuildOutputLinks) == null && (colorValue == null || "auto".equals(colorValue)) && useColorfulOutput) {
23682393
addPlainImageBuilderArg(oHEnableBuildOutputLinks);
23692394
}
23702395
return useColorfulOutput;

0 commit comments

Comments
 (0)