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

com.oracle.svm.jni.access.JNIReflectionDictionary Maven / Gradle / Ivy

There is a newer version: 19.2.1
Show newest version
/*
 * Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package com.oracle.svm.jni.access;

// Checkstyle: allow reflection

import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.function.Function;

import org.graalvm.compiler.word.Word;
import org.graalvm.nativeimage.ImageSingletons;
import org.graalvm.nativeimage.Platform.HOSTED_ONLY;
import org.graalvm.nativeimage.Platforms;
import org.graalvm.word.Pointer;
import org.graalvm.word.WordFactory;

import com.oracle.svm.core.snippets.KnownIntrinsics;
import com.oracle.svm.jni.nativeapi.JNIFieldId;
import com.oracle.svm.jni.nativeapi.JNIMethodId;

import jdk.vm.ci.meta.JavaType;
import jdk.vm.ci.meta.Signature;

/**
 * Provides JNI access to predetermined classes, methods and fields at runtime.
 */
public final class JNIReflectionDictionary {

    static void initialize() {
        ImageSingletons.add(JNIReflectionDictionary.class, new JNIReflectionDictionary());
    }

    public static JNIReflectionDictionary singleton() {
        return ImageSingletons.lookup(JNIReflectionDictionary.class);
    }

    private final Map classesByName = new HashMap<>();
    private final Map, JNIAccessibleClass> classesByClassObject = new HashMap<>();
    private final Map nativeLinkages = new HashMap<>();

    private JNIReflectionDictionary() {
    }

    @Platforms(HOSTED_ONLY.class)
    JNIAccessibleClass addClassIfAbsent(Class classObj, Function, JNIAccessibleClass> mappingFunction) {
        if (!classesByClassObject.containsKey(classObj)) {
            JNIAccessibleClass instance = mappingFunction.apply(classObj);
            classesByClassObject.put(classObj, instance);
            classesByName.put(instance.getInternalName(), instance);
        }
        return classesByClassObject.get(classObj);
    }

    @Platforms(HOSTED_ONLY.class)
    void addLinkages(Map linkages) {
        nativeLinkages.putAll(linkages);
    }

    public Collection getClasses() {
        return Collections.unmodifiableCollection(classesByClassObject.values());
    }

    public Class getClassObjectByName(String name) {
        JNIAccessibleClass clazz = classesByName.get(name);
        return (clazz != null) ? clazz.getClassObject() : null;
    }

    /**
     * Gets the linkage for a native method.
     *
     * @param declaringClass the {@linkplain JavaType#getName() name} of the class declaring the
     *            native method
     * @param name the name of the native method
     * @param descriptor the {@linkplain Signature#toMethodDescriptor() descriptor} of the native
     *            method
     * @return the linkage for the native method or {@code null} if no linkage exists
     */
    public JNINativeLinkage getLinkage(String declaringClass, String name, String descriptor) {
        JNINativeLinkage key = new JNINativeLinkage(declaringClass, name, descriptor);
        return nativeLinkages.get(key);
    }

    public void unsetEntryPoints(String declaringClass) {
        for (JNINativeLinkage linkage : nativeLinkages.keySet()) {
            if (declaringClass.equals(linkage.getDeclaringClassName())) {
                linkage.unsetEntryPoint();
            }
        }
    }

    public JNIMethodId getMethodID(Class classObject, JNIAccessibleMethodDescriptor descriptor, boolean isStatic) {
        JNIMethodId methodID = WordFactory.nullPointer();
        JNIAccessibleClass clazz = classesByClassObject.get(classObject);
        if (clazz != null) {
            JNIAccessibleMethod method = clazz.getMethod(descriptor);
            if (method != null && method.isStatic() == isStatic) {
                // safe because JNIAccessibleMethod is immutable (non-movable)
                methodID = (JNIMethodId) Word.objectToUntrackedPointer(method);
            }
        }
        return methodID;
    }

    public JNIMethodId getMethodID(Class classObject, String name, String signature, boolean isStatic) {
        return getMethodID(classObject, new JNIAccessibleMethodDescriptor(name, signature), isStatic);
    }

    public static JNIAccessibleMethod getMethodByID(JNIMethodId method) {
        Object obj = ((Pointer) method).toObject();
        return KnownIntrinsics.convertUnknownValue(obj, JNIAccessibleMethod.class);
    }

    public JNIAccessibleField getField(Class classObject, String name) {
        JNIAccessibleClass clazz = classesByClassObject.get(classObject);
        return (clazz != null) ? clazz.getField(name) : null;
    }

    public JNIFieldId getFieldID(Class clazz, String name) {
        JNIAccessibleField field = getField(clazz, name);
        return field != null ? field.getId() : WordFactory.zero();
    }

    public String getFieldNameByID(Class classObject, JNIFieldId id) {
        JNIAccessibleClass clazz = classesByClassObject.get(classObject);
        if (clazz != null) {
            for (Entry entry : clazz.getFieldsByName().entrySet()) {
                JNIAccessibleField field = entry.getValue();
                if (id.equal(field.getId())) {
                    return entry.getKey();
                }
            }
        }
        return null;
    }

    public static JNIAccessibleMethodDescriptor getMethodDescriptor(JNIAccessibleMethod method) {
        if (method != null) {
            JNIAccessibleClass clazz = method.getDeclaringClass();
            for (Entry entry : clazz.getMethodsByDescriptor().entrySet()) {
                if (entry.getValue() == method) {
                    return entry.getKey();
                }
            }
        }
        return null;
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy