[GR-39406] Add new class initialization strategy that allows all classes to be used at image build time. #4684
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This PR adds a less strict class initialization mode that allows all classes to be used at image build time. It can be enabled with
-H:+UseNewExperimentalClassInitialization
.The new approach is functional, i.e., it can be used for experiments to see if the new approach is useful and to see if there are compatibility problems.. It is not optimized yet, i.e., far more classes will be initialized at image run time so peak performance will be lower for now. The new approach will only be enabled by default once all optimizations of the current approach are also available for the new approach.
Current approach
--initialize-at-build-time
option, theorg.graalvm.nativeimage.hosted.RuntimeClassInitialization
class then can be called from aFeature
, ...Problems with the current approach
New less restricted approach
Compatibility impact
All code that is currently properly configured for build-time initialization (i.e., all classes that end up on the image heap are explicitly listed as "initialize at build time") using command line options will continue to work. It will allow users to run more code at image build time, or reduce the number of classes explicitly marked for initialization at build time.
In the current system, classes that are proven to be safe for build time initialization are treated the same as classes explicitly configured for build-time initialization. This is no longer possible with the new architecture. If an instance of such a class is in the image heap, then image build will fail with the an error that the class is not allowed in the image heap.
Examples
To make the examples more readable, each class name has a suffix:
_InitAtBuildTime
: The class is explicitly marked as "initialize at build time" by the user_InitAtRunTime
: The class is not marked as initialization at build time and therefore initialized at run time. This is the default.We use the pseudo-field
$$initialized
to refer to the class initialization status of a class.Example 1
Assume that
B_InitAtRunTime
is not used by aFeature
and therefore does not get initialized by the image builder VM.A_InitAtBuildTime
gets initialized by the image builder VM because of its manual designation, regardless of how it is used at image build time. So in the image builder, the static field values areThe same values are written out into the image heap.
After the class
B_InitAtRunTime
gets initialized at run time, the static fields have the following values:Example 2
Assume that
B_InitAtRunTime
is used by aFeature
and therefore gets initialized by the image builder VM. So in the image builder, the static field values areIn the written out image, the following static field values are in the image heap:
After the class
B_InitAtRunTime
gets initialized at run time, the static fields have the following values:The usage of
B_InitAtRunTime
at image build time has a bad side effect onA_InitAtBuildTime
, whose field got incremented twice. But by explicitly markingA_InitAtBuildTime
as initialize-at-build-time, the user has acknowledged that such side effects are understood.Our recommendation for users should be: Only mark a class for initialization at build time if it does not have 1) any mutable static state (including any mutable data structures reachable from static final fields), and 2) a class initializer that accesses any mutable state of another class.
Example 3
The feature code runs before static analysis and initializes the static field. So in the image builder, the static field values are
This is a correct use of build time initialization: classes that store information computed a build time must be marked as "initialize at build time".
Example 4
The image build fails: The image heap must not only contain instances of classes that are marked as "initialize at build time".