< prev index next >

src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.services/src/jdk/vm/ci/services/Services.java

Print this page

        

*** 20,188 **** * or visit www.oracle.com if you need additional information or have any * questions. */ package jdk.vm.ci.services; - import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; ! import java.util.Formatter; ! import java.util.Iterator; ! import java.util.ServiceConfigurationError; ! import java.util.ServiceLoader; ! import java.util.Set; /** ! * A mechanism for accessing service providers via JVMCI. */ public final class Services { ! private Services() { ! } ! ! private static int getJavaSpecificationVersion() { ! String value = System.getProperty("java.specification.version"); ! if (value.startsWith("1.")) { ! value = value.substring(2); ! } ! return Integer.parseInt(value); ! } ! ! /** ! * The integer value corresponding to the value of the {@code java.specification.version} system ! * property after any leading {@code "1."} has been stripped. ! */ ! public static final int JAVA_SPECIFICATION_VERSION = getJavaSpecificationVersion(); ! // Use reflection so that this compiles on Java 8 ! private static final Method getModule; ! private static final Method getPackages; ! private static final Method addUses; ! private static final Method isExported; ! private static final Method addExports; ! ! static { ! if (JAVA_SPECIFICATION_VERSION >= 9) { ! try { ! getModule = Class.class.getMethod("getModule"); ! Class<?> moduleClass = getModule.getReturnType(); ! getPackages = moduleClass.getMethod("getPackages"); ! addUses = moduleClass.getMethod("addUses", Class.class); ! isExported = moduleClass.getMethod("isExported", String.class, moduleClass); ! addExports = moduleClass.getMethod("addExports", String.class, moduleClass); ! } catch (NoSuchMethodException | SecurityException e) { ! throw new InternalError(e); ! } ! } else { ! getModule = null; ! getPackages = null; ! addUses = null; ! isExported = null; ! addExports = null; ! } } @SuppressWarnings("unchecked") ! static <T> T invoke(Method method, Object receiver, Object... args) { try { ! return (T) method.invoke(receiver, args); ! } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { throw new InternalError(e); } } /** ! * Performs any required security checks and dynamic reconfiguration to allow the module of a ! * given class to access the classes in the JVMCI module. ! * ! * Note: This API uses {@link Class} instead of {@code Module} to provide backwards ! * compatibility for JVMCI clients compiled against a JDK release earlier than 9. ! * ! * @param requestor a class requesting access to the JVMCI module for its module ! * @throws SecurityException if a security manager is present and it denies ! * {@link JVMCIPermission} */ ! public static void exportJVMCITo(Class<?> requestor) { ! SecurityManager sm = System.getSecurityManager(); ! if (sm != null) { ! sm.checkPermission(new JVMCIPermission()); ! } ! if (JAVA_SPECIFICATION_VERSION >= 9) { ! Object jvmci = invoke(getModule, Services.class); ! Object requestorModule = invoke(getModule, requestor); ! if (jvmci != requestorModule) { ! Set<String> packages = invoke(getPackages, jvmci); ! for (String pkg : packages) { ! // Export all JVMCI packages dynamically instead ! // of requiring a long list of --add-exports ! // options on the JVM command line. ! boolean exported = invoke(isExported, jvmci, pkg, requestorModule); ! if (!exported) { ! invoke(addExports, jvmci, pkg, requestorModule); ! } ! } ! } } } /** ! * Gets an {@link Iterable} of the JVMCI providers available for a given service. ! * ! * @throws SecurityException if a security manager is present and it denies ! * {@link JVMCIPermission} */ ! public static <S> Iterable<S> load(Class<S> service) { SecurityManager sm = System.getSecurityManager(); if (sm != null) { sm.checkPermission(new JVMCIPermission()); } ! if (JAVA_SPECIFICATION_VERSION >= 9) { ! Object jvmci = invoke(getModule, Services.class); ! invoke(addUses, jvmci, service); ! } ! ! // Restrict JVMCI clients to be on the class path or module path ! return ServiceLoader.load(service, ClassLoader.getSystemClassLoader()); } /** ! * Gets the JVMCI provider for a given service for which at most one provider must be available. ! * ! * @param service the service whose provider is being requested ! * @param required specifies if an {@link InternalError} should be thrown if no provider of ! * {@code service} is available ! * @throws SecurityException if a security manager is present and it denies ! * {@link JVMCIPermission} */ ! public static <S> S loadSingle(Class<S> service, boolean required) { ! SecurityManager sm = System.getSecurityManager(); ! if (sm != null) { ! sm.checkPermission(new JVMCIPermission()); ! } ! if (JAVA_SPECIFICATION_VERSION >= 9) { ! Object jvmci = invoke(getModule, Services.class); ! invoke(addUses, jvmci, service); ! } ! // Restrict JVMCI clients to be on the class path or module path ! Iterable<S> providers = ServiceLoader.load(service, ClassLoader.getSystemClassLoader()); ! S singleProvider = null; try { ! for (Iterator<S> it = providers.iterator(); it.hasNext();) { ! singleProvider = it.next(); ! if (it.hasNext()) { ! throw new InternalError(String.format("Multiple %s providers found", service.getName())); ! } ! } ! } catch (ServiceConfigurationError e) { ! // If the service is required we will bail out below. ! } ! if (singleProvider == null && required) { ! String javaHome = System.getProperty("java.home"); ! String vmName = System.getProperty("java.vm.name"); ! Formatter errorMessage = new Formatter(); ! errorMessage.format("The VM does not expose required service %s.%n", service.getName()); ! errorMessage.format("Currently used Java home directory is %s.%n", javaHome); ! errorMessage.format("Currently used VM configuration is: %s", vmName); ! throw new UnsupportedOperationException(errorMessage.toString()); } - return singleProvider; } } --- 20,85 ---- * or visit www.oracle.com if you need additional information or have any * questions. */ package jdk.vm.ci.services; import java.lang.reflect.Method; ! import java.util.Map; /** ! * Provides utilities needed by JVMCI clients. */ public final class Services { ! // This class must be compilable and executable on JDK 8 since it's used in annotation ! // processors while building JDK 9 so use of API added in JDK 9 is made via reflection. ! private Services() { } @SuppressWarnings("unchecked") ! private static Map<String, String> initSavedProperties() throws InternalError { try { ! Class<?> vmClass = Class.forName("jdk.internal.misc.VM"); ! Method m = vmClass.getMethod("getSavedProperties"); ! return (Map<String, String>) m.invoke(null); ! } catch (Exception e) { throw new InternalError(e); } } + static final Map<String, String> SAVED_PROPERTIES = initSavedProperties(); + static final boolean JVMCI_ENABLED = Boolean.parseBoolean(SAVED_PROPERTIES.get("jdk.internal.vm.ci.enabled")); + /** ! * Checks that JVMCI is enabled in the VM and throws an error if it isn't. */ ! static void checkJVMCIEnabled() { ! if (!JVMCI_ENABLED) { ! throw new Error("The EnableJVMCI VM option must be true (i.e., -XX:+EnableJVMCI) to use JVMCI"); } } /** ! * Gets an unmodifiable copy of the system properties saved when {@link System} is initialized. */ ! public static Map<String, String> getSavedProperties() { ! checkJVMCIEnabled(); SecurityManager sm = System.getSecurityManager(); if (sm != null) { sm.checkPermission(new JVMCIPermission()); } ! return SAVED_PROPERTIES; } /** ! * Causes the JVMCI subsystem to be initialized if it isn't already initialized. */ ! public static void initializeJVMCI() { ! checkJVMCIEnabled(); try { ! Class.forName("jdk.vm.ci.runtime.JVMCI"); ! } catch (ClassNotFoundException e) { ! throw new InternalError(e); } } }
< prev index next >