Skip to content

Commit a90687f

Browse files
committed
Flip the class initialization flag
1 parent 9907449 commit a90687f

File tree

8 files changed

+43
-21
lines changed

8 files changed

+43
-21
lines changed

docs/reference-manual/native-image/BuildOutput.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,15 @@ This feature is currently only available for Linux AArch64 and leverages pointer
258258
259259
The build output may contain one or more of the following recommendations that help you get the best out of Native Image.
260260
261+
#### <a name="recommendation-init"></a>`INIT`: Use the Strict Image Heap Configuration
262+
263+
Start using `--strict-image-heap` to reduce the amount of configuration and prepare for future GraalVM releases where this will be the default.
264+
This mode requires only the classes that are stored in the image heap to be marked with `--initialize-at-build-time`.
265+
This effectively reduces the number of configuration entries necessary to achieve build-time initialization.
266+
When adopting the new mode it is best to start introducing build-time initialization from scratch.
267+
During this process, it is best to select individual classes (as opposed to whole packages) for build time initialization.
268+
Also, before migrating to the new flag make sure to update all framework dependencies to the latest versions as they might need to migrate too.
269+
261270
#### <a name="recommendation-awt"></a>`AWT`: Missing Reachability Metadata for Abstract Window Toolkit
262271
263272
The Native Image analysis has included classes from the [`java.awt` package](https://docs.oracle.com/en/java/javase/17/docs/api/java.desktop/java/awt/package-summary.html) but could not find any reachability metadata for it.

substratevm/CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ This changelog summarizes major changes to GraalVM Native Image.
1010
* (GR-45841) BellSoft added support for the JFR event ThreadCPULoad.
1111
* (GR-45994) Removed the option `-H:EnableSignalAPI`. Please use the runtime option `EnableSignalHandling` if it is necessary to enable or disable signal handling explicitly.
1212
* (GR-39406) Simulation of class initializer: Class initializer of classes that are not marked for initialization at image build time are simulated at image build time to avoid executing them at image run time.
13-
* (GR-39406) All classes can now be used at image build time, even when they are not explicitly configured as `--initialize-at-build-time`. Note, however, that still only classes configured as `--initialize-at-build-time` are allowed in the image heap.
13+
* (GR-39406) New option `--strict-image-heap`: All classes can now be used at image build time, even when they are not explicitly configured as `--initialize-at-build-time`. Note, however, that still only classes configured as `--initialize-at-build-time` are allowed in the image heap. Adopt this option as it will become the default in the next release of GraalVM.
1414
* (GR-46392) Add `--parallelism` option to control how many threads are used by the build process.
1515
* (GR-46392) Add build resources section to the build output that shows the memory and thread limits of the build process.
1616
* (GR-38994) Together with Red Hat, we added support for `-XX:+HeapDumpOnOutOfMemoryError`.

substratevm/mx.substratevm/mx_substratevm.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1514,9 +1514,9 @@ def build_and_test_clinittest_image(native_image, args, new_class_init_policy):
15141514
mx.ensure_dir_exists(build_dir)
15151515

15161516
if new_class_init_policy:
1517-
policy_args = svm_experimental_options(['-H:-UseDeprecatedOldClassInitialization', '-H:+SimulateClassInitializer']) + ['--features=com.oracle.svm.test.clinit.TestClassInitializationFeatureNewPolicyFeature']
1517+
policy_args = svm_experimental_options(['-H:+StrictImageHeap', '-H:+SimulateClassInitializer']) + ['--features=com.oracle.svm.test.clinit.TestClassInitializationFeatureNewPolicyFeature']
15181518
else:
1519-
policy_args = svm_experimental_options(['-H:+UseDeprecatedOldClassInitialization', '-H:-SimulateClassInitializer']) + ['--features=com.oracle.svm.test.clinit.TestClassInitializationFeatureOldPolicyFeature']
1519+
policy_args = svm_experimental_options(['-H:-SimulateClassInitializer']) + ['--features=com.oracle.svm.test.clinit.TestClassInitializationFeatureOldPolicyFeature']
15201520

15211521
# Build and run the example
15221522
binary_path = join(build_dir, 'clinittest')

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ProgressReporterFeature.java

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@
2727
import java.util.List;
2828
import java.util.function.Supplier;
2929

30-
import com.oracle.svm.util.LogUtils;
3130
import org.graalvm.nativeimage.ImageSingletons;
3231

3332
import com.oracle.svm.core.BuildArtifacts;
@@ -38,12 +37,15 @@
3837
import com.oracle.svm.core.feature.InternalFeature;
3938
import com.oracle.svm.core.jni.access.JNIAccessibleClass;
4039
import com.oracle.svm.core.jni.access.JNIReflectionDictionary;
40+
import com.oracle.svm.core.option.SubstrateOptionsParser;
4141
import com.oracle.svm.hosted.FeatureImpl.AfterCompilationAccessImpl;
4242
import com.oracle.svm.hosted.FeatureImpl.BeforeImageWriteAccessImpl;
4343
import com.oracle.svm.hosted.ProgressReporter.DirectPrinter;
44+
import com.oracle.svm.hosted.classinitialization.ClassInitializationOptions;
4445
import com.oracle.svm.hosted.jdk.JNIRegistrationSupport;
4546
import com.oracle.svm.hosted.util.CPUTypeAArch64;
4647
import com.oracle.svm.hosted.util.CPUTypeAMD64;
48+
import com.oracle.svm.util.LogUtils;
4749

4850
@AutomaticallyRegisteredFeature
4951
public class ProgressReporterFeature implements InternalFeature {
@@ -90,6 +92,10 @@ public void createAdditionalArtifacts(@SuppressWarnings("unused") BuildArtifacts
9092

9193
protected List<UserRecommendation> getRecommendations() {
9294
return List.of(// in order of appearance:
95+
new UserRecommendation("INIT",
96+
"Adopt " + SubstrateOptionsParser.commandArgument(ClassInitializationOptions.StrictImageHeap, "+", "strict-initial-heap", true, false) +
97+
" to prepare for the next GraalVM release.",
98+
() -> !ClassInitializationOptions.StrictImageHeap.getValue()),
9399
new UserRecommendation("AWT", "Use the tracing agent to collect metadata for AWT.", ProgressReporterFeature::recommendTraceAgentForAWT),
94100
new UserRecommendation("HEAP", "Set max heap for improved and more predictable memory usage.", () -> SubstrateGCOptions.MaxHeapSize.getValue() == 0),
95101
new UserRecommendation("CPU", "Enable more CPU features with '-march=native' for improved performance.", ProgressReporterFeature::recommendMArchNative));
@@ -126,7 +132,8 @@ private static boolean recommendTraceAgentForAWT() {
126132
public record UserRecommendation(String id, String description, Supplier<Boolean> isApplicable) {
127133
public UserRecommendation(String id, String description, Supplier<Boolean> isApplicable) {
128134
assert id.toUpperCase().equals(id) && id.length() < 5 : "id must be uppercase and have fewer than 5 chars";
129-
assert description.length() < 74 : "description must have fewer than 74 chars to fit in terminal";
135+
int maxLength = 74;
136+
assert description.length() < maxLength : "description must have fewer than " + maxLength + " chars to fit in terminal. Length: " + description.length();
130137
this.id = id;
131138
this.description = description;
132139
this.isApplicable = isApplicable;

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/classinitialization/ClassInitializationFeature.java

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -168,13 +168,16 @@ private Object checkImageHeapInstance(Object obj) {
168168
}
169169
});
170170

171-
if (!ClassInitializationOptions.UseDeprecatedOldClassInitialization.getValue()) {
171+
if (ClassInitializationOptions.StrictImageHeap.getValue()) {
172172
msg += """
173-
174-
If you see this error while migrating to a newer GraalVM release, please note that the class initialization strategy has changed in GraalVM for JDK 21.
175-
All classes can now be used at image build time. However, only classes explicitly marked as --initialize-at-build-time are allowed to be in the image heap.
176-
This rule is now strictly enforced, i.e., the problem might be solvable by registering the reported type as --initialize-at-build-time.
177-
""".replaceAll("\n", System.lineSeparator());
173+
If you are seeing this message after enabling %s, this means that some objects ended up in the image heap without their type being marked with --initialize-at-build-time.
174+
To fix this, include %s in your configuration. If the classes do not originate from your code, it is advised to update all library or framework dependencies to the latest version before addressing this error.
175+
Please address this problem to be prepared for future releases of GraalVM.
176+
"""
177+
.replaceAll("\n", System.lineSeparator())
178+
.formatted(
179+
SubstrateOptionsParser.commandArgument(ClassInitializationOptions.StrictImageHeap, typeName, "strict-image-heap", true, false),
180+
SubstrateOptionsParser.commandArgument(ClassInitializationOptions.ClassInitialization, typeName, "initialize-at-build-time", true, false));
178181
}
179182

180183
msg += System.lineSeparator() + "The following detailed trace displays from which field in the code the object was reached.";

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/classinitialization/ClassInitializationOptions.java

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
import com.oracle.svm.core.option.APIOption;
3838
import com.oracle.svm.core.option.HostedOptionKey;
3939
import com.oracle.svm.core.option.LocatableMultiOptionValue;
40+
import com.oracle.svm.core.util.UserError;
4041

4142
public final class ClassInitializationOptions {
4243

@@ -100,9 +101,13 @@ private static class InitializationValueEager extends InitializationValueTransfo
100101
@Option(help = "Assert class initialization is specified for all classes.", type = OptionType.Debug)//
101102
public static final HostedOptionKey<Boolean> AssertInitializationSpecifiedForAllClasses = new HostedOptionKey<>(false);
102103

103-
@Option(help = "Use the old class initialization strategy that does not allow all classes to be used at image build time.", type = OptionType.Expert, //
104-
deprecated = true, deprecationMessage = "Temporary flag to restore the class initialization behavior of older GraalVM versions. The old class initialization strategy will be removed in a future version of GraalVM.") //
105-
public static final HostedOptionKey<Boolean> UseDeprecatedOldClassInitialization = new HostedOptionKey<>(false);
104+
@APIOption(name = "strict-image-heap")//
105+
@Option(help = "Enable the strict image heap mode that allows all classes to be used at build-time but also requires types of all objects in the heap to be explicitly marked for build-time initialization.", type = OptionType.User) //
106+
public static final HostedOptionKey<Boolean> StrictImageHeap = new HostedOptionKey<>(false, k -> {
107+
if (k.hasBeenSet() && Boolean.FALSE.equals(k.getValue())) {
108+
throw UserError.abort("Strict image heap mode cannot be explicitly disabled.");
109+
}
110+
});
106111

107112
@Option(help = "Simulate the effects of class initializer at image build time, to avoid class initialization at run time.", type = OptionType.Expert)//
108113
public static final HostedOptionKey<Boolean> SimulateClassInitializer = new HostedOptionKey<>(true);

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/classinitialization/ClassInitializationSupport.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,6 @@
5252
import com.oracle.svm.core.util.UserError;
5353
import com.oracle.svm.hosted.ImageClassLoader;
5454
import com.oracle.svm.hosted.LinkAtBuildTimeSupport;
55-
import com.oracle.svm.util.LogUtils;
5655

5756
import jdk.internal.misc.Unsafe;
5857
import jdk.vm.ci.meta.MetaAccessProvider;
@@ -89,8 +88,7 @@ public abstract class ClassInitializationSupport implements RuntimeClassInitiali
8988
final MetaAccessProvider metaAccess;
9089

9190
public static ClassInitializationSupport create(MetaAccessProvider metaAccess, ImageClassLoader loader) {
92-
if (ClassInitializationOptions.UseDeprecatedOldClassInitialization.getValue()) {
93-
LogUtils.warning("Using old deprecated class initialization strategy. Only classes that are marked explicitly as '--initialize-at-build-time' can be used during image generation.");
91+
if (!ClassInitializationOptions.StrictImageHeap.getValue()) {
9492
return new ProvenSafeClassInitializationSupport(metaAccess, loader);
9593
}
9694
return new AllowAllHostedUsagesClassInitializationSupport(metaAccess, loader);

substratevm/src/com.oracle.svm.test/src/com/oracle/svm/test/clinit/TestClassInitialization.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -727,8 +727,8 @@ public void afterImageWrite(AfterImageWriteAccess access) {
727727
}
728728

729729
/**
730-
* For testing with {@link ClassInitializationOptions#UseDeprecatedOldClassInitialization} set to
731-
* true and simulation of class initializer disabled.
730+
* For testing with {@link ClassInitializationOptions#StrictImageHeap} set to false and simulation
731+
* of class initializer disabled.
732732
*/
733733
class TestClassInitializationFeatureOldPolicyFeature extends TestClassInitializationFeature {
734734

@@ -765,8 +765,8 @@ void checkClass(Class<?> checkedClass, boolean checkSafeEarly, boolean checkSafe
765765
}
766766

767767
/**
768-
* For testing with {@link ClassInitializationOptions#UseDeprecatedOldClassInitialization} set to
769-
* false and simulation of class initializer enabled.
768+
* For testing with {@link ClassInitializationOptions#StrictImageHeap} set to true and simulation of
769+
* class initializer enabled.
770770
*/
771771
class TestClassInitializationFeatureNewPolicyFeature extends TestClassInitializationFeature {
772772
@Override

0 commit comments

Comments
 (0)