use of org.graalvm.nativeimage.Feature.DuringAnalysisAccess in project graal by oracle.
the class ReflectionDataBuilder method duringAnalysis.
protected void duringAnalysis(DuringAnalysisAccess a) {
DuringAnalysisAccessImpl access = (DuringAnalysisAccessImpl) a;
if (!modified) {
return;
}
modified = false;
access.requireAnalysisIteration();
Method reflectionDataMethod = findMethod(Class.class, "reflectionData");
Class<?> originalReflectionDataClass = access.getImageClassLoader().findClassByName("java.lang.Class$ReflectionData");
Field declaredFieldsField = findField(originalReflectionDataClass, "declaredFields");
Field publicFieldsField = findField(originalReflectionDataClass, "publicFields");
Field declaredMethodsField = findField(originalReflectionDataClass, "declaredMethods");
Field publicMethodsField = findField(originalReflectionDataClass, "publicMethods");
Field declaredConstructorsField = findField(originalReflectionDataClass, "declaredConstructors");
Field publicConstructorsField = findField(originalReflectionDataClass, "publicConstructors");
Field declaredPublicFieldsField = findField(originalReflectionDataClass, "declaredPublicFields");
Field declaredPublicMethodsField = findField(originalReflectionDataClass, "declaredPublicMethods");
Field[] emptyFields = new Field[0];
Method[] emptyMethods = new Method[0];
Constructor<?>[] emptyConstructors = new Constructor<?>[0];
Set<Class<?>> allClasses = new HashSet<>(reflectionClasses);
reflectionMethods.stream().map(method -> method.getDeclaringClass()).forEach(clazz -> allClasses.add(clazz));
reflectionFields.stream().map(field -> field.getDeclaringClass()).forEach(clazz -> allClasses.add(clazz));
/*
* We need to find all classes that have an enclosingMethod or enclosingConstructor.
* Unfortunately, there is no reverse lookup (ask a Method or Constructor about the classes
* they contain), so we need to iterate through all types that have been loaded so far.
* Accessing the original java.lang.Class for a ResolvedJavaType is not 100% reliable,
* especially in the case of class and method substitutions. But it is the best we can do
* here, and we assume that user code that requires reflection support is not using
* substitutions.
*/
for (AnalysisType aType : access.getUniverse().getTypes()) {
Class<?> originalClass = aType.getJavaClass();
if (originalClass != null && enclosingMethodOrConstructor(originalClass) != null) {
/*
* We haven an enclosing method or constructor for this class, so we add the class
* to the set of processed classes so that the ReflectionData is initialized below.
*/
allClasses.add(originalClass);
}
}
for (Class<?> clazz : allClasses) {
DynamicHub hub = access.getHostVM().dynamicHub(access.getMetaAccess().lookupJavaType(clazz));
if (reflectionClasses.contains(clazz)) {
ClassForNameSupport.registerClass(clazz);
}
/*
* Ensure all internal fields of the original Class.ReflectionData object are
* initialized. Calling the public methods triggers lazy initialization of the fields.
*/
clazz.getDeclaredFields();
clazz.getFields();
clazz.getDeclaredMethods();
clazz.getMethods();
clazz.getDeclaredConstructors();
clazz.getConstructors();
try {
Object originalReflectionData = reflectionDataMethod.invoke(clazz);
hub.setReflectionData(new DynamicHub.ReflectionData(filter(declaredFieldsField.get(originalReflectionData), reflectionFields, emptyFields), filter(publicFieldsField.get(originalReflectionData), reflectionFields, emptyFields), filter(declaredMethodsField.get(originalReflectionData), reflectionMethods, emptyMethods), filter(publicMethodsField.get(originalReflectionData), reflectionMethods, emptyMethods), filter(declaredConstructorsField.get(originalReflectionData), reflectionMethods, emptyConstructors), filter(publicConstructorsField.get(originalReflectionData), reflectionMethods, emptyConstructors), nullaryConstructor(declaredConstructorsField.get(originalReflectionData), reflectionMethods), filter(declaredPublicFieldsField.get(originalReflectionData), reflectionFields, emptyFields), filter(declaredPublicMethodsField.get(originalReflectionData), reflectionMethods, emptyMethods), enclosingMethodOrConstructor(clazz)));
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
throw VMError.shouldNotReachHere(ex);
}
}
}
Aggregations