org.qbicc.plugin.reachability.RuntimeReflectionRoots Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of qbicc-plugin-reachability Show documentation
Show all versions of qbicc-plugin-reachability Show documentation
Support for evaluating program reachability
package org.qbicc.plugin.reachability;
import org.qbicc.context.AttachmentKey;
import org.qbicc.context.CompilationContext;
import org.qbicc.interpreter.VmClassLoader;
import org.qbicc.plugin.apploader.AppClassLoader;
import org.qbicc.type.definition.DefinedTypeDefinition;
import org.qbicc.type.definition.LoadedTypeDefinition;
import org.qbicc.type.definition.VerifyFailedException;
import org.qbicc.type.definition.element.ConstructorElement;
import org.qbicc.type.definition.element.ExecutableElement;
import org.qbicc.type.definition.element.FieldElement;
import org.qbicc.type.definition.element.MethodElement;
import org.qbicc.type.definition.element.StaticFieldElement;
import org.qbicc.type.descriptor.TypeDescriptor;
import java.lang.reflect.Constructor;
import java.lang.reflect.Executable;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
/**
* Tracks runtime-reflection operations and ensures that the necessary
* Classes, Methods, etc. are preserved in the final native image.
*/
public class RuntimeReflectionRoots {
private static final AttachmentKey KEY = new AttachmentKey<>();
private final CompilationContext ctxt;
private final Set accessedClasses = ConcurrentHashMap.newKeySet();
private final Set accessedMethods = ConcurrentHashMap.newKeySet();
private final Set accessedFields = ConcurrentHashMap.newKeySet();
private RuntimeReflectionRoots(final CompilationContext ctxt) {
this.ctxt = ctxt;
}
public static RuntimeReflectionRoots get(CompilationContext ctxt) {
RuntimeReflectionRoots info = ctxt.getAttachment(KEY);
if (info == null) {
info = new RuntimeReflectionRoots(ctxt);
RuntimeReflectionRoots appearing = ctxt.putAttachmentIfAbsent(KEY, info);
if (appearing != null) {
info = appearing;
}
}
return info;
}
public void reportStats() {
ReachabilityInfo.LOGGER.debugf(" Reflectively accessed classes: %s", accessedClasses.size());
ReachabilityInfo.LOGGER.debugf(" Reflectively accessed methods: %s", accessedMethods.size());
ReachabilityInfo.LOGGER.debugf(" Reflectively accessed fields: %s", accessedFields.size());
}
public void registerClass(Class> clazz) {
LoadedTypeDefinition ltd = classToType(clazz);
if (ltd != null) {
accessedClasses.add(ltd);
}
}
public void registerMethods(Executable... methods) {
for (Executable e: methods) {
LoadedTypeDefinition ltd = classToType(e.getDeclaringClass());
if (ltd != null) {
if (e instanceof Constructor c) {
int ci = ltd.findSingleConstructorIndex(ce -> {
if (ce.getParameters().size() != c.getParameterCount()) {
return false;
}
Class>[] hostPtypes = c.getParameterTypes();
List qbiccPTypes = ce.getDescriptor().getParameterTypes();
for (int i=0; i {
if (!me.getName().equals(m.getName()) ||
me.isStatic() != Modifier.isStatic(m.getModifiers()) ||
me.getParameters().size() != m.getParameterCount()) {
return false;
}
Class>[] hostPtypes = m.getParameterTypes();
List qbiccPTypes = me.getDescriptor().getParameterTypes();
for (int i=0; i clazz) {
VmClassLoader appCl = AppClassLoader.get(ctxt).getAppClassLoader();
try {
DefinedTypeDefinition dtd = appCl.getClassContext().findDefinedType(clazz.getName().replace(".", "/"));
return dtd == null ? null: dtd.load();
} catch (VerifyFailedException e) {
ctxt.warning("Unable to load type %s due to VerifyFailedException %s", clazz.getName(), e.getMessage());
return null;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy