src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.services/src/jdk/vm/ci/services/Services.java
Index Unified diffs Context diffs Sdiffs Frames Patch New Old Previous File Next File open Sdiff src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.services/src/jdk/vm/ci/services

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

Print this page


   1 /*
   2  * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 package jdk.vm.ci.services;
  24 










  25 import java.util.Map;


  26 import java.util.Set;
  27 
  28 import jdk.internal.misc.VM;

  29 
  30 /**
  31  * Provides utilities needed by JVMCI clients.
  32  */
  33 public final class Services {
  34 
  35     // This class must be compilable and executable on JDK 8 since it's used in annotation
  36     // processors while building JDK 9 so use of API added in JDK 9 is made via reflection.
  37 
  38     /**
  39      * Guards code that should be run when building a native image but should be excluded from
  40      * (being compiled into) the image. Such code must be directly guarded by an {@code if}
  41      * statement on this field - the guard cannot be behind a method call.
  42      */
  43     public static final boolean IS_BUILDING_NATIVE_IMAGE;
  44 
  45     /**
  46      * Guards code that should only be run in native image. Such code must be directly guarded by an
  47      * {@code if} statement on this field - the guard cannot be behind a method call.
  48      *
  49      * The value of this field seen during analysis and compilation of an SVM image must be
  50      * {@code true}.
  51      */
  52     public static final boolean IS_IN_NATIVE_IMAGE;
  53 
  54     static {
  55         /*
  56          * Prevents javac from constant folding use of this field. It is set to true in the SVM
  57          * image via substitution during image building.
  58          */
  59         IS_IN_NATIVE_IMAGE = false;
  60         IS_BUILDING_NATIVE_IMAGE = false;
  61     }
  62 
  63     private Services() {
  64     }
  65 
  66     static final Map<String, String> SAVED_PROPERTIES = VM.getSavedProperties();
  67     static final boolean JVMCI_ENABLED = Boolean.parseBoolean(SAVED_PROPERTIES.get("jdk.internal.vm.ci.enabled"));
  68 
  69     /**
  70      * Checks that JVMCI is enabled in the VM and throws an error if it isn't.
  71      */
  72     static void checkJVMCIEnabled() {
  73         if (!JVMCI_ENABLED) {
  74             throw new Error("The EnableJVMCI VM option must be true (i.e., -XX:+EnableJVMCI) to use JVMCI");
  75         }
  76     }
  77 
  78     /**
  79      * Gets an unmodifiable copy of the system properties saved when {@link System} is initialized.
  80      */
  81     public static Map<String, String> getSavedProperties() {
  82         checkJVMCIEnabled();
  83         SecurityManager sm = System.getSecurityManager();
  84         if (sm != null) {
  85             sm.checkPermission(new JVMCIPermission());
  86         }
  87         return SAVED_PROPERTIES;














  88     }
  89 
  90     /**
  91      * Causes the JVMCI subsystem to be initialized if it isn't already initialized.
  92      */
  93     public static void initializeJVMCI() {
  94         checkJVMCIEnabled();
  95         try {
  96             Class.forName("jdk.vm.ci.runtime.JVMCI");
  97         } catch (ClassNotFoundException e) {
  98             throw new InternalError(e);
  99         }
 100     }
 101 













































































 102     /**
 103      * Opens all JVMCI packages to {@code otherModule}.
 104      */
 105     static void openJVMCITo(Module otherModule) {
 106         Module jvmci = Services.class.getModule();
 107         if (jvmci != otherModule) {
 108             Set<String> packages = jvmci.getPackages();
 109             for (String pkg : packages) {
 110                 boolean opened = jvmci.isOpen(pkg, otherModule);
 111                 if (!opened) {
 112                     jvmci.addOpens(pkg, otherModule);
 113                 }
 114             }
 115         }
 116     }























































































































 117 }
   1 /*
   2  * Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 package jdk.vm.ci.services;
  24 
  25 import java.io.ByteArrayInputStream;
  26 import java.io.ByteArrayOutputStream;
  27 import java.io.DataInputStream;
  28 import java.io.DataOutputStream;
  29 import java.io.IOException;
  30 import java.util.ArrayList;
  31 import java.util.Collections;
  32 import java.util.Formatter;
  33 import java.util.HashMap;
  34 import java.util.List;
  35 import java.util.Map;
  36 import java.util.Properties;
  37 import java.util.ServiceLoader;
  38 import java.util.Set;
  39 
  40 import jdk.internal.misc.VM;
  41 import jdk.internal.reflect.Reflection;
  42 
  43 /**
  44  * Provides utilities needed by JVMCI clients.
  45  */
  46 public final class Services {
  47 
  48     // This class must be compilable and executable on JDK 8 since it's used in annotation
  49     // processors while building JDK 9 so use of API added in JDK 9 is made via reflection.
  50 
  51     /**
  52      * Guards code that should be run when building an JVMCI shared library but should be excluded
  53      * from (being compiled into) the library. Such code must be directly guarded by an {@code if}
  54      * statement on this field - the guard cannot be behind a method call.
  55      */
  56     public static final boolean IS_BUILDING_NATIVE_IMAGE = Boolean.parseBoolean(VM.getSavedProperty("jdk.vm.ci.services.aot"));
  57 
  58     /**
  59      * Guards code that should only be run in a JVMCI shared library. Such code must be directly
  60      * guarded by an {@code if} statement on this field - the guard cannot be behind a method call.
  61      *
  62      * The value of this field in a JVMCI shared library runtime must be {@code true}.

  63      */
  64     public static final boolean IS_IN_NATIVE_IMAGE;

  65     static {
  66         /*
  67          * Prevents javac from constant folding use of this field. It is set to true by the process
  68          * that builds the shared library.
  69          */
  70         IS_IN_NATIVE_IMAGE = false;

  71     }
  72 
  73     private Services() {
  74     }
  75 
  76     private static volatile Map<String, String> savedProperties = VM.getSavedProperties();
  77     static final boolean JVMCI_ENABLED = Boolean.parseBoolean(savedProperties.get("jdk.internal.vm.ci.enabled"));
  78 
  79     /**
  80      * Checks that JVMCI is enabled in the VM and throws an error if it isn't.
  81      */
  82     static void checkJVMCIEnabled() {
  83         if (!JVMCI_ENABLED) {
  84             throw new Error("The EnableJVMCI VM option must be true (i.e., -XX:+EnableJVMCI) to use JVMCI");
  85         }
  86     }
  87 
  88     /**
  89      * Gets an unmodifiable copy of the system properties saved when {@link System} is initialized.
  90      */
  91     public static Map<String, String> getSavedProperties() {
  92         checkJVMCIEnabled();
  93         SecurityManager sm = System.getSecurityManager();
  94         if (sm != null) {
  95             sm.checkPermission(new JVMCIPermission());
  96         }
  97         return savedProperties;
  98     }
  99 
 100     /**
 101      * Helper method equivalent to {@link #getSavedProperties()}{@code .getOrDefault(name, def)}.
 102      */
 103     public static String getSavedProperty(String name, String def) {
 104         return Services.getSavedProperties().getOrDefault(name, def);
 105     }
 106 
 107     /**
 108      * Helper method equivalent to {@link #getSavedProperties()}{@code .get(name)}.
 109      */
 110     public static String getSavedProperty(String name) {
 111         return Services.getSavedProperties().get(name);
 112     }
 113 
 114     /**
 115      * Causes the JVMCI subsystem to be initialized if it isn't already initialized.
 116      */
 117     public static void initializeJVMCI() {
 118         checkJVMCIEnabled();
 119         try {
 120             Class.forName("jdk.vm.ci.runtime.JVMCI");
 121         } catch (ClassNotFoundException e) {
 122             throw new InternalError(e);
 123         }
 124     }
 125 
 126     private static boolean jvmciEnabled = true;
 127 
 128     /**
 129      * When {@code -XX:-UseJVMCIClassLoader} is in use, JVMCI classes are loaded via the boot class
 130      * loader. When {@code null} is the second argument to
 131      * {@link ServiceLoader#load(Class, ClassLoader)}, service lookup will use the system class
 132      * loader and thus find application classes which violates the API of {@link #load} and
 133      * {@link #loadSingle}. To avoid this, a class loader that simply delegates to the boot class
 134      * loader is used.
 135      */
 136     static class LazyBootClassPath {
 137         static final ClassLoader bootClassPath = new ClassLoader(null) {
 138         };
 139     }
 140 
 141     private static ClassLoader findBootClassLoaderChild(ClassLoader start) {
 142         ClassLoader cl = start;
 143         while (cl.getParent() != null) {
 144             cl = cl.getParent();
 145         }
 146         return cl;
 147     }
 148 
 149     private static final Map<Class<?>, List<?>> servicesCache = IS_BUILDING_NATIVE_IMAGE ? new HashMap<>() : null;
 150 
 151     @SuppressWarnings("unchecked")
 152     private static <S> Iterable<S> load0(Class<S> service) {
 153         if (IS_IN_NATIVE_IMAGE || IS_BUILDING_NATIVE_IMAGE) {
 154             List<?> list = servicesCache.get(service);
 155             if (list != null) {
 156                 return (Iterable<S>) list;
 157             }
 158             if (IS_IN_NATIVE_IMAGE) {
 159                 throw new InternalError(String.format("No %s providers found when building native image", service.getName()));
 160             }
 161         }
 162 
 163         Iterable<S> providers = Collections.emptyList();
 164         if (jvmciEnabled) {
 165             ClassLoader cl = null;
 166             try {
 167                 cl = getJVMCIClassLoader();
 168                 if (cl == null) {
 169                     cl = LazyBootClassPath.bootClassPath;
 170                     // JVMCI classes are loaded via the boot class loader.
 171                     // If we use null as the second argument to ServiceLoader.load,
 172                     // service loading will use the system class loader
 173                     // and find classes on the application class path. Since we
 174                     // don't want this, we use a loader that is as close to the
 175                     // boot class loader as possible (since it is impossible
 176                     // to force service loading to use only the boot class loader).
 177                     cl = findBootClassLoaderChild(ClassLoader.getSystemClassLoader());
 178                 }
 179                 providers = ServiceLoader.load(service, cl);
 180             } catch (UnsatisfiedLinkError e) {
 181                 jvmciEnabled = false;
 182             } catch (InternalError e) {
 183                 if (e.getMessage().equals("JVMCI is not enabled")) {
 184                     jvmciEnabled = false;
 185                 } else {
 186                     throw e;
 187                 }
 188             }
 189         }
 190         if (IS_BUILDING_NATIVE_IMAGE) {
 191             synchronized (servicesCache) {
 192                 ArrayList<S> providersList = new ArrayList<>();
 193                 for (S provider : providers) {
 194                     providersList.add(provider);
 195                 }
 196                 servicesCache.put(service, providersList);
 197                 providers = providersList;
 198             }
 199         }
 200         return providers;
 201     }
 202 
 203     /**
 204      * Opens all JVMCI packages to {@code otherModule}.
 205      */
 206     static void openJVMCITo(Module otherModule) {
 207         Module jvmci = Services.class.getModule();
 208         if (jvmci != otherModule) {
 209             Set<String> packages = jvmci.getPackages();
 210             for (String pkg : packages) {
 211                 boolean opened = jvmci.isOpen(pkg, otherModule);
 212                 if (!opened) {
 213                     jvmci.addOpens(pkg, otherModule);
 214                 }
 215             }
 216         }
 217     }
 218 
 219     /**
 220      * Gets an {@link Iterable} of the JVMCI providers available for a given service.
 221      *
 222      * @throws SecurityException if a security manager is present and it denies <tt>
 223      *             {@link RuntimePermission}("jvmci")</tt>
 224      */
 225     public static <S> Iterable<S> load(Class<S> service) {
 226         SecurityManager sm = System.getSecurityManager();
 227         if (sm != null) {
 228             sm.checkPermission(new JVMCIPermission());
 229         }
 230         return load0(service);
 231     }
 232 
 233     /**
 234      * Gets the JVMCI provider for a given service for which at most one provider must be available.
 235      *
 236      * @param service the service whose provider is being requested
 237      * @param required specifies if an {@link InternalError} should be thrown if no provider of
 238      *            {@code service} is available
 239      * @throws SecurityException if a security manager is present and it denies <tt>
 240      *             {@link RuntimePermission}("jvmci")</tt>
 241      */
 242     public static <S> S loadSingle(Class<S> service, boolean required) {
 243         SecurityManager sm = System.getSecurityManager();
 244         if (sm != null) {
 245             sm.checkPermission(new JVMCIPermission());
 246         }
 247         Iterable<S> providers = load0(service);
 248 
 249         S singleProvider = null;
 250         for (S provider : providers) {
 251             if (singleProvider != null) {
 252                 throw new InternalError(String.format("Multiple %s providers found: %s, %s", service.getName(), singleProvider.getClass().getName(), provider.getClass().getName()));
 253             }
 254             singleProvider = provider;
 255         }
 256         if (singleProvider == null && required) {
 257             String javaHome = Services.getSavedProperty("java.home");
 258             String vmName = Services.getSavedProperty("java.vm.name");
 259             Formatter errorMessage = new Formatter();
 260             errorMessage.format("The VM does not expose required service %s.%n", service.getName());
 261             errorMessage.format("Currently used Java home directory is %s.%n", javaHome);
 262             errorMessage.format("Currently used VM configuration is: %s", vmName);
 263             throw new UnsupportedOperationException(errorMessage.toString());
 264         }
 265         return singleProvider;
 266     }
 267 
 268     static {
 269         Reflection.registerMethodsToFilter(Services.class, Set.of("getJVMCIClassLoader"));
 270     }
 271 
 272     /**
 273      * Gets the JVMCI class loader.
 274      *
 275      * @throws InternalError with the {@linkplain Throwable#getMessage() message}
 276      *             {@code "JVMCI is not enabled"} iff JVMCI is not enabled
 277      */
 278     private static ClassLoader getJVMCIClassLoader() {
 279         if (IS_IN_NATIVE_IMAGE) {
 280             return null;
 281         }
 282         return ClassLoader.getSystemClassLoader();
 283     }
 284 
 285     /**
 286      * Serializes the {@linkplain #getSavedProperties() saved system properties} to a byte array for
 287      * the purpose of {@linkplain #initializeSavedProperties(byte[]) initializing} the initial
 288      * properties in the JVMCI shared library.
 289      */
 290     @VMEntryPoint
 291     private static byte[] serializeSavedProperties() throws IOException {
 292         if (IS_IN_NATIVE_IMAGE) {
 293             throw new InternalError("Can only serialize saved properties in HotSpot runtime");
 294         }
 295         Map<String, String> props = Services.getSavedProperties();
 296 
 297         // Compute size of output on the assumption that
 298         // all system properties have ASCII names and values
 299         int estimate = 4;
 300         for (Map.Entry<String, String> e : props.entrySet()) {
 301             String name = e.getKey();
 302             String value = e.getValue();
 303             estimate += (2 + (name.length())) + (2 + (value.length()));
 304         }
 305 
 306         ByteArrayOutputStream baos = new ByteArrayOutputStream(estimate);
 307         DataOutputStream out = new DataOutputStream(baos);
 308         out.writeInt(props.size());
 309         for (Map.Entry<String, String> e : props.entrySet()) {
 310             String name = e.getKey();
 311             String value = e.getValue();
 312             out.writeUTF(name);
 313             out.writeUTF(value);
 314         }
 315         return baos.toByteArray();
 316     }
 317 
 318     /**
 319      * Initialized the {@linkplain #getSavedProperties() saved system properties} in the JVMCI
 320      * shared library from the {@linkplain #serializeSavedProperties() serialized saved properties}
 321      * in the HotSpot runtime.
 322      */
 323     @VMEntryPoint
 324     private static void initializeSavedProperties(byte[] serializedProperties) throws IOException {
 325         if (!IS_IN_NATIVE_IMAGE) {
 326             throw new InternalError("Can only initialize saved properties in JVMCI shared library runtime");
 327         }
 328         DataInputStream in = new DataInputStream(new ByteArrayInputStream(serializedProperties));
 329         Map<String, String> props = new HashMap<>(in.readInt());
 330         while (in.available() != 0) {
 331             String name = in.readUTF();
 332             String value = in.readUTF();
 333             props.put(name, value);
 334         }
 335         savedProperties = Collections.unmodifiableMap(props);
 336     }
 337 }
src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.services/src/jdk/vm/ci/services/Services.java
Index Unified diffs Context diffs Sdiffs Frames Patch New Old Previous File Next File