All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.qbicc.plugin.reachability.RuntimeReflectionRoots Maven / Gradle / Ivy

There is a newer version: 0.77.0
Show newest version
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