Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

No build time init of classes used in UnsafeAccessedFieldBuildItem #39831

Merged
merged 1 commit into from
Apr 4, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -78,28 +78,6 @@ public void write(String s, byte[] bytes) {
MethodCreator beforeAn = file.getMethodCreator("beforeAnalysis", "V", BEFORE_ANALYSIS_ACCESS);
TryBlock overallCatch = beforeAn.tryBlock();

ResultHandle beforeAnalysisParam = beforeAn.getMethodParam(0);

MethodCreator registerAsUnsafeAccessed = file
.getMethodCreator("registerAsUnsafeAccessed", void.class, Feature.BeforeAnalysisAccess.class)
.setModifiers(Modifier.PRIVATE | Modifier.STATIC);
for (UnsafeAccessedFieldBuildItem unsafeAccessedField : unsafeAccessedFields) {
TryBlock tc = registerAsUnsafeAccessed.tryBlock();
ResultHandle declaringClassHandle = tc.invokeStaticMethod(
ofMethod(Class.class, "forName", Class.class, String.class),
tc.load(unsafeAccessedField.getDeclaringClass()));
ResultHandle fieldHandle = tc.invokeVirtualMethod(
ofMethod(Class.class, "getDeclaredField", Field.class, String.class), declaringClassHandle,
tc.load(unsafeAccessedField.getFieldName()));
tc.invokeInterfaceMethod(
ofMethod(Feature.BeforeAnalysisAccess.class, "registerAsUnsafeAccessed", void.class, Field.class),
registerAsUnsafeAccessed.getMethodParam(0), fieldHandle);
CatchBlockCreator cc = tc.addCatch(Throwable.class);
cc.invokeVirtualMethod(ofMethod(Throwable.class, "printStackTrace", void.class), cc.getCaughtException());
}
registerAsUnsafeAccessed.returnVoid();
overallCatch.invokeStaticMethod(registerAsUnsafeAccessed.getMethodDescriptor(), beforeAnalysisParam);

overallCatch.invokeStaticMethod(BUILD_TIME_INITIALIZATION,
overallCatch.marshalAsArray(String.class, overallCatch.load(""))); // empty string means initialize everything

Expand Down Expand Up @@ -179,6 +157,35 @@ public void write(String s, byte[] bytes) {
overallCatch.invokeStaticMethod(runtimeReinitializedClasses.getMethodDescriptor());
}

// Ensure registration of fields being accessed through unsafe is done last to ensure that the class
// initialization configuration is done first. Registering the fields before configuring class initialization
// may results in classes being marked for runtime initialization even if not explicitly requested.
if (!unsafeAccessedFields.isEmpty()) {
ResultHandle beforeAnalysisParam = beforeAn.getMethodParam(0);
MethodCreator registerAsUnsafeAccessed = file
.getMethodCreator("registerAsUnsafeAccessed", void.class, Feature.BeforeAnalysisAccess.class)
.setModifiers(Modifier.PRIVATE | Modifier.STATIC);
ResultHandle thisClass = registerAsUnsafeAccessed.loadClassFromTCCL(GRAAL_FEATURE);
ResultHandle cl = registerAsUnsafeAccessed
.invokeVirtualMethod(ofMethod(Class.class, "getClassLoader", ClassLoader.class), thisClass);
for (UnsafeAccessedFieldBuildItem unsafeAccessedField : unsafeAccessedFields) {
TryBlock tc = registerAsUnsafeAccessed.tryBlock();
ResultHandle declaringClassHandle = tc.invokeStaticMethod(
ofMethod(Class.class, "forName", Class.class, String.class, boolean.class, ClassLoader.class),
tc.load(unsafeAccessedField.getDeclaringClass()), tc.load(false), cl);
ResultHandle fieldHandle = tc.invokeVirtualMethod(
ofMethod(Class.class, "getDeclaredField", Field.class, String.class), declaringClassHandle,
tc.load(unsafeAccessedField.getFieldName()));
tc.invokeInterfaceMethod(
ofMethod(Feature.BeforeAnalysisAccess.class, "registerAsUnsafeAccessed", void.class, Field.class),
registerAsUnsafeAccessed.getMethodParam(0), fieldHandle);
CatchBlockCreator cc = tc.addCatch(Throwable.class);
cc.invokeVirtualMethod(ofMethod(Throwable.class, "printStackTrace", void.class), cc.getCaughtException());
}
registerAsUnsafeAccessed.returnVoid();
overallCatch.invokeStaticMethod(registerAsUnsafeAccessed.getMethodDescriptor(), beforeAnalysisParam);
}

CatchBlockCreator print = overallCatch.addCatch(Throwable.class);
print.invokeVirtualMethod(ofMethod(Throwable.class, "printStackTrace", void.class), print.getCaughtException());

Expand Down