Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions sdk/src/org.graalvm.nativeimage/snapshot.sigtest
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@ fld public final static java.lang.String PROPERTY_IMAGE_CODE_VALUE_RUNTIME = "ru
fld public final static java.lang.String PROPERTY_IMAGE_KIND_KEY = "org.graalvm.nativeimage.kind"
fld public final static java.lang.String PROPERTY_IMAGE_KIND_VALUE_EXECUTABLE = "executable"
fld public final static java.lang.String PROPERTY_IMAGE_KIND_VALUE_SHARED_LIBRARY = "shared"
fld public final static java.lang.String PROPERTY_NATIVE_IMAGE_PREFIX = "org.graalvm.nativeimage."
meth public static boolean inImageBuildtimeCode()
meth public static boolean inImageCode()
meth public static boolean inImageRuntimeCode()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,13 @@ public final class ImageInfo {
private ImageInfo() {
}

/**
* Holds a name that is a prefix for all native-image properties.
*
* @since 25.0
*/
public static final String PROPERTY_NATIVE_IMAGE_PREFIX = "org.graalvm.nativeimage.";

/**
* Holds the string that is the name of the system property providing information about the
* context in which code is currently executing. If the property returns the string given by
Expand All @@ -64,7 +71,7 @@ private ImageInfo() {
*
* @since 19.0
*/
public static final String PROPERTY_IMAGE_CODE_KEY = "org.graalvm.nativeimage.imagecode";
public static final String PROPERTY_IMAGE_CODE_KEY = PROPERTY_NATIVE_IMAGE_PREFIX + "imagecode";

/**
* Holds the string that will be returned by the system property for
Expand All @@ -91,7 +98,7 @@ private ImageInfo() {
*
* @since 19.0
*/
public static final String PROPERTY_IMAGE_KIND_KEY = "org.graalvm.nativeimage.kind";
public static final String PROPERTY_IMAGE_KIND_KEY = PROPERTY_NATIVE_IMAGE_PREFIX + "kind";

/**
* Holds the string that will be returned by the system property for
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,12 @@
*/
package com.oracle.svm.core;

import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.Objects;
import java.util.Set;

import org.graalvm.collections.EconomicSet;
import org.graalvm.nativeimage.ImageInfo;
import org.graalvm.nativeimage.Platform;
import org.graalvm.nativeimage.Platforms;

Expand All @@ -42,9 +44,19 @@
import jdk.graal.compiler.options.OptionType;

/**
* What makes it into the future-defaults must not be an experimental feature that can be rolled
* back. The changes must be aligning native image with the Java spec and must be thoroughly
* Enables the --future-defaults=value flag that is used for evolution of Native Image semantics.
* Each enabled future default also sets a build-time, and run-time property named
* <code>'{@value #SYSTEM_PROPERTY_PREFIX}{@literal <property-name>}'</code> to <code>true</code>.
* That property can be used by the community to adjust their code to work both with the previous
* and with the new behavior of Native Image.
* </p>
* Note 1: What makes it into the future-defaults must not be an experimental feature that can be
* rolled back. The changes must be aligning native image with the Java spec and must be thoroughly
* reviewed.
* </p>
* Note 2: future defaults can not be simply removed as user code can depend on the system property
* values that are set by the option. When removing a future-default option, one has to leave the
* system property both a build time and at run time set to <code>true</code>.
*/
public class FutureDefaultsOptions {
private static final String OPTION_NAME = "future-defaults";
Expand All @@ -57,26 +69,36 @@ public class FutureDefaultsOptions {

public static final String RUN_TIME_INITIALIZE_JDK_REASON = "Initialize JDK classes at run time (--" + OPTION_NAME + " includes " + RUN_TIME_INITIALIZE_JDK_NAME + ")";

private static final Set<String> ALL_VALUES = Set.of(RUN_TIME_INITIALIZE_JDK_NAME, TREAT_NAME_AS_TYPE_NAME, ALL_NAME, NONE_NAME);
public static final String SYSTEM_PROPERTY_PREFIX = ImageInfo.PROPERTY_NATIVE_IMAGE_PREFIX + OPTION_NAME + ".";

private static final Set<String> ALL_FUTURE_DEFAULTS = Set.of(RUN_TIME_INITIALIZE_JDK_NAME, TREAT_NAME_AS_TYPE_NAME);
private static final Set<String> ALL_COMMANDS = Set.of(ALL_NAME, NONE_NAME);

private static String futureDefaultsAllValues() {
return StringUtil.joinSingleQuoted(ALL_VALUES);
return StringUtil.joinSingleQuoted(getAllValues());
}

private static Set<String> getAllValues() {
Set<String> result = new LinkedHashSet<>(ALL_FUTURE_DEFAULTS.size() + ALL_COMMANDS.size());
result.addAll(ALL_FUTURE_DEFAULTS);
result.addAll(ALL_COMMANDS);
return result;
}

static {
assert ALL_VALUES.stream().allMatch(futureDefaultsAllValues()::contains) : "A value is missing in the user-facing help text";
assert getAllValues().stream().allMatch(futureDefaultsAllValues()::contains) : "A value is missing in the user-facing help text";
}

@APIOption(name = OPTION_NAME, defaultValue = DEFAULT_NAME) //
@Option(help = "file:doc-files/FutureDefaultsHelp.txt", type = OptionType.User) //
static final HostedOptionKey<AccumulatingLocatableMultiOptionValue.Strings> FutureDefaults = new HostedOptionKey<>(
AccumulatingLocatableMultiOptionValue.Strings.buildWithCommaDelimiter());

private static EconomicSet<String> futureDefaults;
private static Set<String> futureDefaults;

@Platforms(Platform.HOSTED_ONLY.class)
public static void parseAndVerifyOptions() {
futureDefaults = EconomicSet.create(ALL_VALUES.size());
futureDefaults = new LinkedHashSet<>(getAllValues().size());
var valuesWithOrigin = FutureDefaults.getValue().getValuesWithOrigins();
valuesWithOrigin.forEach(valueWithOrigin -> {
String value = valueWithOrigin.value();
Expand All @@ -87,7 +109,7 @@ public static void parseAndVerifyOptions() {
futureDefaultsAllValues());
}

if (!ALL_VALUES.contains(value)) {
if (!getAllValues().contains(value)) {
throw UserError.abort("The '%s' option from %s contains invalid value '%s'. It can only contain: %s.",
SubstrateOptionsParser.commandArgument(FutureDefaults, value),
valueWithOrigin.origin(),
Expand All @@ -104,23 +126,32 @@ public static void parseAndVerifyOptions() {
futureDefaults.clear();
}

futureDefaults.add(value);
if (value.equals(ALL_NAME)) {
futureDefaults.addAll(ALL_FUTURE_DEFAULTS);
} else {
futureDefaults.add(value);
}
});

/* Set build-time properties for user features */
for (String futureDefault : getFutureDefaults()) {
System.setProperty(FutureDefaultsOptions.SYSTEM_PROPERTY_PREFIX + futureDefault, Boolean.TRUE.toString());
}
}

private static EconomicSet<String> getFutureDefaults() {
return Objects.requireNonNull(futureDefaults, "must be initialized before usage");
public static Set<String> getFutureDefaults() {
return Collections.unmodifiableSet(Objects.requireNonNull(futureDefaults, "must be initialized before usage"));
}

public static boolean allFutureDefaults() {
return getFutureDefaults().contains(ALL_NAME);
return getFutureDefaults().containsAll(ALL_FUTURE_DEFAULTS);
}

public static boolean isJDKInitializedAtRunTime() {
return allFutureDefaults() || getFutureDefaults().contains(RUN_TIME_INITIALIZE_JDK_NAME);
return getFutureDefaults().contains(RUN_TIME_INITIALIZE_JDK_NAME);
}

public static boolean treatNameAsType() {
return allFutureDefaults() || getFutureDefaults().contains(TREAT_NAME_AS_TYPE_NAME);
return getFutureDefaults().contains(TREAT_NAME_AS_TYPE_NAME);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
import org.graalvm.nativeimage.hosted.RuntimeSystemProperties;
import org.graalvm.nativeimage.impl.RuntimeSystemPropertiesSupport;

import com.oracle.svm.core.FutureDefaultsOptions;
import com.oracle.svm.core.SubstrateOptions;
import com.oracle.svm.core.SubstrateUtil;
import com.oracle.svm.core.VM;
Expand Down Expand Up @@ -143,6 +144,10 @@ protected SystemPropertiesSupport() {

initializeProperty(ImageInfo.PROPERTY_IMAGE_CODE_KEY, ImageInfo.PROPERTY_IMAGE_CODE_VALUE_RUNTIME);

for (String futureDefault : FutureDefaultsOptions.getFutureDefaults()) {
initializeProperty(FutureDefaultsOptions.SYSTEM_PROPERTY_PREFIX + futureDefault, Boolean.TRUE.toString());
}

ArrayList<LazySystemProperty> lazyProperties = new ArrayList<>();
lazyProperties.add(new LazySystemProperty(UserSystemProperty.NAME, this::userNameValue));
lazyProperties.add(new LazySystemProperty(UserSystemProperty.HOME, this::userHomeValue));
Expand Down