Skip to content

Commit

Permalink
Merge pull request #20232 from zakkak/fix-20226
Browse files Browse the repository at this point in the history
Add GraalVM 21.3 compatibility support for resource registration
  • Loading branch information
geoand authored Sep 24, 2021
2 parents 47412a1 + b5361d8 commit 30f34f6
Showing 1 changed file with 75 additions and 39 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -72,12 +72,13 @@ public class NativeImageAutoFeatureStep {
private static final MethodDescriptor RERUN_INITIALIZATION = ofMethod(
"org.graalvm.nativeimage.impl.RuntimeClassInitializationSupport",
"rerunInitialization", void.class, Class.class, String.class);
private static final MethodDescriptor RESOURCES_REGISTRY_ADD_RESOURCES = ofMethod(
"com.oracle.svm.core.configure.ResourcesRegistry",
"addResources", void.class, String.class);
private static final MethodDescriptor RESOURCES_REGISTRY_IGNORE_RESOURCES = ofMethod(
"com.oracle.svm.core.configure.ResourcesRegistry",
"ignoreResources", void.class, String.class);
private static final MethodDescriptor LOOKUP_METHOD = ofMethod(
"com.oracle.svm.util.ReflectionUtil",
"lookupMethod", Method.class, Class.class, String.class, Class[].class);
private static final MethodDescriptor FOR_NAME = ofMethod(
Class.class, "forName", Class.class, String.class, boolean.class, ClassLoader.class);
private static final MethodDescriptor INVOKE = ofMethod(
Method.class, "invoke", Object.class, Object.class, Object[].class);
static final String RUNTIME_REFLECTION = RuntimeReflection.class.getName();
static final String JNI_RUNTIME_ACCESS = "com.oracle.svm.core.jni.JNIRuntimeAccess";
static final String BEFORE_ANALYSIS_ACCESS = Feature.BeforeAnalysisAccess.class.getName();
Expand Down Expand Up @@ -230,16 +231,63 @@ public void write(String s, byte[] bytes) {
ResultHandle resourcesRegistrySingleton = overallCatch.invokeStaticMethod(IMAGE_SINGLETONS_LOOKUP,
overallCatch.loadClass("com.oracle.svm.core.configure.ResourcesRegistry"));
TryBlock tc = overallCatch.tryBlock();

ResultHandle currentThread = tc.invokeStaticMethod(ofMethod(Thread.class, "currentThread", Thread.class));
ResultHandle tccl = tc.invokeVirtualMethod(ofMethod(Thread.class, "getContextClassLoader", ClassLoader.class),
currentThread);
AssignableResultHandle resourcesArgTypes = tc.createVariable(Class[].class);
AssignableResultHandle resourcesArgs = tc.createVariable(Object[].class);
AssignableResultHandle argsIndex = tc.createVariable(int.class);

BranchResult graalVm21_3Test = tc.ifGreaterEqualZero(
tc.invokeVirtualMethod(VERSION_COMPARE_TO,
tc.invokeStaticMethod(VERSION_CURRENT),
tc.marshalAsArray(int.class, tc.load(21), tc.load(3))));
/* GraalVM >= 21.3 */
BytecodeCreator greaterThan21_2 = graalVm21_3Test.trueBranch();
ResultHandle argTypes = greaterThan21_2.newArray(Class.class, greaterThan21_2.load(2));
ResultHandle configurationConditionClass = greaterThan21_2.invokeStaticMethod(FOR_NAME,
greaterThan21_2.load("org.graalvm.nativeimage.impl.ConfigurationCondition"),
greaterThan21_2.load(false), tccl);
greaterThan21_2.writeArrayValue(argTypes, 0, configurationConditionClass);
greaterThan21_2.writeArrayValue(argTypes, 1, greaterThan21_2.loadClass(String.class));
greaterThan21_2.assign(resourcesArgTypes, argTypes);
ResultHandle args = greaterThan21_2.newArray(Object.class, greaterThan21_2.load(2));
ResultHandle alwaysTrueMethod = greaterThan21_2.invokeStaticMethod(LOOKUP_METHOD,
configurationConditionClass,
greaterThan21_2.load("alwaysTrue"),
greaterThan21_2.newArray(Class.class, greaterThan21_2.load(0)));
ResultHandle alwaysTrueResult = greaterThan21_2.invokeVirtualMethod(INVOKE,
alwaysTrueMethod, greaterThan21_2.loadNull(),
greaterThan21_2.newArray(Object.class, greaterThan21_2.load(0)));
greaterThan21_2.writeArrayValue(args, 0, alwaysTrueResult);
greaterThan21_2.assign(resourcesArgs, args);
greaterThan21_2.assign(argsIndex, greaterThan21_2.load(1));

/* GraalVM < 21.3 */
BytecodeCreator smallerThan21_3 = graalVm21_3Test.falseBranch();
argTypes = smallerThan21_3.newArray(Class.class, smallerThan21_3.load(1));
smallerThan21_3.writeArrayValue(argTypes, 0, smallerThan21_3.loadClass(String.class));
smallerThan21_3.assign(resourcesArgTypes, argTypes);
args = smallerThan21_3.newArray(Object.class, smallerThan21_3.load(1));
smallerThan21_3.assign(resourcesArgs, args);
smallerThan21_3.assign(argsIndex, smallerThan21_3.load(0));

ResultHandle ignoreResourcesMethod = tc.invokeStaticMethod(LOOKUP_METHOD,
tc.loadClass("com.oracle.svm.core.configure.ResourcesRegistry"),
tc.load("ignoreResources"), resourcesArgTypes);
ResultHandle addResourcesMethod = tc.invokeStaticMethod(LOOKUP_METHOD,
tc.loadClass("com.oracle.svm.core.configure.ResourcesRegistry"),
tc.load("addResources"), resourcesArgTypes);

for (NativeImageResourcePatternsBuildItem resourcePatternsItem : resourcePatterns) {
for (String pattern : resourcePatternsItem.getExcludePatterns()) {
tc.invokeInterfaceMethod(RESOURCES_REGISTRY_IGNORE_RESOURCES, resourcesRegistrySingleton,
overallCatch.load(pattern));
tc.writeArrayValue(resourcesArgs, argsIndex, tc.load(pattern));
tc.invokeVirtualMethod(INVOKE, ignoreResourcesMethod, resourcesRegistrySingleton, resourcesArgs);
}
for (String pattern : resourcePatternsItem.getIncludePatterns()) {
tc.invokeInterfaceMethod(
RESOURCES_REGISTRY_ADD_RESOURCES,
resourcesRegistrySingleton,
tc.load(pattern));
tc.writeArrayValue(resourcesArgs, argsIndex, tc.load(pattern));
tc.invokeVirtualMethod(INVOKE, addResourcesMethod, resourcesRegistrySingleton, resourcesArgs);
}
}
CatchBlockCreator cc = tc.addCatch(Throwable.class);
Expand Down Expand Up @@ -538,39 +586,30 @@ private MethodDescriptor createRegisterSerializationForClassMethod(ClassCreator
ofMethod(Thread.class, "getContextClassLoader", ClassLoader.class),
currentThread);

MethodDescriptor forNameMethodDescriptor = ofMethod(Class.class, "forName", Class.class, String.class, boolean.class,
ClassLoader.class);

MethodDescriptor lookupMethod = ofMethod("com.oracle.svm.util.ReflectionUtil", "lookupMethod", Method.class,
Class.class, String.class,
Class[].class);
MethodDescriptor invokeMethodDescriptor = ofMethod(Method.class, "invoke", Object.class, Object.class,
Object[].class);

BranchResult graalVm21_3Test = tc.ifGreaterEqualZero(
tc.invokeVirtualMethod(VERSION_COMPARE_TO, tc.invokeStaticMethod(VERSION_CURRENT),
tc.marshalAsArray(int.class, tc.load(21), tc.load(3))));

BytecodeCreator greaterThan21_3 = graalVm21_3Test.trueBranch();
ResultHandle runtimeSerializationClass = greaterThan21_3.invokeStaticMethod(forNameMethodDescriptor,
ResultHandle runtimeSerializationClass = greaterThan21_3.invokeStaticMethod(FOR_NAME,
greaterThan21_3.load("org.graalvm.nativeimage.hosted.RuntimeSerialization"),
greaterThan21_3.load(false), tccl);
ResultHandle registerArgTypes = greaterThan21_3.newArray(Class.class, greaterThan21_3.load(1));
greaterThan21_3.writeArrayValue(registerArgTypes, 0, greaterThan21_3.loadClass(Class[].class));
ResultHandle registerLookupMethod = greaterThan21_3.invokeStaticMethod(lookupMethod, runtimeSerializationClass,
ResultHandle registerLookupMethod = greaterThan21_3.invokeStaticMethod(LOOKUP_METHOD, runtimeSerializationClass,
greaterThan21_3.load("register"), registerArgTypes);
ResultHandle registerArgs = greaterThan21_3.newArray(Object.class, greaterThan21_3.load(1));
ResultHandle classesToRegister = greaterThan21_3.newArray(Class.class, greaterThan21_3.load(1));
greaterThan21_3.writeArrayValue(classesToRegister, 0, clazz);
greaterThan21_3.writeArrayValue(registerArgs, 0, classesToRegister);
greaterThan21_3.invokeVirtualMethod(invokeMethodDescriptor, registerLookupMethod,
greaterThan21_3.invokeVirtualMethod(INVOKE, registerLookupMethod,
greaterThan21_3.loadNull(), registerArgs);
greaterThan21_3.returnValue(null);

ResultHandle serializationRegistryClass = tc.invokeStaticMethod(forNameMethodDescriptor,
ResultHandle serializationRegistryClass = tc.invokeStaticMethod(FOR_NAME,
tc.load("com.oracle.svm.core.jdk.serialize.SerializationRegistry"),
tc.load(false), tccl);
ResultHandle addReflectionsClass = tc.invokeStaticMethod(forNameMethodDescriptor,
ResultHandle addReflectionsClass = tc.invokeStaticMethod(FOR_NAME,
tc.load("com.oracle.svm.reflect.serialize.hosted.SerializationFeature"),
tc.load(false), tccl);

Expand All @@ -581,39 +620,36 @@ private MethodDescriptor createRegisterSerializationForClassMethod(ClassCreator
ResultHandle addReflectionsLookupArgs = tc.newArray(Class.class, tc.load(2));
tc.writeArrayValue(addReflectionsLookupArgs, 0, tc.loadClass(Class.class));
tc.writeArrayValue(addReflectionsLookupArgs, 1, tc.loadClass(Class.class));
ResultHandle addReflectionsLookupMethod = tc.invokeStaticMethod(lookupMethod, addReflectionsClass,
ResultHandle addReflectionsLookupMethod = tc.invokeStaticMethod(LOOKUP_METHOD, addReflectionsClass,
tc.load("addReflections"), addReflectionsLookupArgs);

ResultHandle reflectionFactory = tc.invokeStaticMethod(
ofMethod("sun.reflect.ReflectionFactory", "getReflectionFactory", "sun.reflect.ReflectionFactory"));

AssignableResultHandle newSerializationConstructor = tc.createVariable(Constructor.class);

ResultHandle externalizableClass = tc.invokeStaticMethod(
forNameMethodDescriptor,
tc.load("java.io.Externalizable"), tc.load(false), tccl);
ResultHandle externalizableClass = tc.invokeStaticMethod(FOR_NAME, tc.load("java.io.Externalizable"), tc.load(false),
tccl);

BranchResult isExternalizable = tc
.ifTrue(tc.invokeVirtualMethod(ofMethod(Class.class, "isAssignableFrom", boolean.class, Class.class),
externalizableClass, clazz));
BytecodeCreator ifIsExternalizable = isExternalizable.trueBranch();

ResultHandle array1 = ifIsExternalizable.newArray(Class.class, tc.load(1));
ResultHandle classClass = ifIsExternalizable.invokeStaticMethod(
forNameMethodDescriptor,
ResultHandle classClass = ifIsExternalizable.invokeStaticMethod(FOR_NAME,
ifIsExternalizable.load("java.lang.Class"), ifIsExternalizable.load(false), tccl);
ifIsExternalizable.writeArrayValue(array1, 0, classClass);

ResultHandle externalizableLookupMethod = ifIsExternalizable.invokeStaticMethod(
lookupMethod,
ResultHandle externalizableLookupMethod = ifIsExternalizable.invokeStaticMethod(LOOKUP_METHOD,
ifIsExternalizable.loadClass(ObjectStreamClass.class), ifIsExternalizable.load("getExternalizableConstructor"),
array1);

ResultHandle array2 = ifIsExternalizable.newArray(Object.class, tc.load(1));
ifIsExternalizable.writeArrayValue(array2, 0, clazz);

ResultHandle externalizableConstructor = ifIsExternalizable.invokeVirtualMethod(
invokeMethodDescriptor, externalizableLookupMethod, ifIsExternalizable.loadNull(), array2);
INVOKE, externalizableLookupMethod, ifIsExternalizable.loadNull(), array2);

ResultHandle externalizableConstructorClass = ifIsExternalizable.invokeVirtualMethod(
ofMethod(Constructor.class, "getDeclaringClass", Class.class),
Expand All @@ -622,7 +658,7 @@ private MethodDescriptor createRegisterSerializationForClassMethod(ClassCreator
ResultHandle addReflectionsArgs1 = ifIsExternalizable.newArray(Class.class, tc.load(2));
ifIsExternalizable.writeArrayValue(addReflectionsArgs1, 0, clazz);
ifIsExternalizable.writeArrayValue(addReflectionsArgs1, 1, externalizableConstructorClass);
ifIsExternalizable.invokeVirtualMethod(invokeMethodDescriptor, addReflectionsLookupMethod,
ifIsExternalizable.invokeVirtualMethod(INVOKE, addReflectionsLookupMethod,
ifIsExternalizable.loadNull(), addReflectionsArgs1);

ifIsExternalizable.returnValue(null);
Expand Down Expand Up @@ -655,11 +691,11 @@ private MethodDescriptor createRegisterSerializationForClassMethod(ClassCreator
newSerializationConstructor);

ResultHandle getConstructorAccessor = tc.invokeStaticMethod(
lookupMethod, tc.loadClass(Constructor.class), tc.load("getConstructorAccessor"),
LOOKUP_METHOD, tc.loadClass(Constructor.class), tc.load("getConstructorAccessor"),
tc.newArray(Class.class, tc.load(0)));

ResultHandle accessor = tc.invokeVirtualMethod(
invokeMethodDescriptor, getConstructorAccessor, newSerializationConstructor,
INVOKE, getConstructorAccessor, newSerializationConstructor,
tc.newArray(Object.class, tc.load(0)));

tc.invokeVirtualMethod(
Expand All @@ -669,7 +705,7 @@ private MethodDescriptor createRegisterSerializationForClassMethod(ClassCreator
ResultHandle addReflectionsArgs2 = tc.newArray(Class.class, tc.load(2));
tc.writeArrayValue(addReflectionsArgs2, 0, clazz);
tc.writeArrayValue(addReflectionsArgs2, 1, newSerializationConstructorClass);
tc.invokeVirtualMethod(invokeMethodDescriptor, addReflectionsLookupMethod, tc.loadNull(), addReflectionsArgs2);
tc.invokeVirtualMethod(INVOKE, addReflectionsLookupMethod, tc.loadNull(), addReflectionsArgs2);

addSerializationForClass.returnValue(null);

Expand Down

0 comments on commit 30f34f6

Please sign in to comment.