comparison graal/com.oracle.jvmci.service/src/com/oracle/jvmci/service/Services.java @ 21614:2f92172fa320

Truffle and NFI implementations are now accessed via JVMCI services instead of being hard coded in the VM (JBS:GRAAL-51)
author Doug Simon <doug.simon@oracle.com>
date Sun, 31 May 2015 13:42:47 +0200
parents 71b338926f2e
children 9966b358bc2b
comparison
equal deleted inserted replaced
21613:60154926b513 21614:2f92172fa320
27 import java.util.*; 27 import java.util.*;
28 28
29 import sun.reflect.*; 29 import sun.reflect.*;
30 30
31 /** 31 /**
32 * A mechanism on top of the standard {@link ServiceLoader} that enables a runtime to efficiently 32 * A mechanism on top of the standard {@link ServiceLoader} that enables JVMCI enabled runtime to
33 * load services marked by {@link Service}. This may be important for services loaded early in the 33 * efficiently load services marked by {@link Service}. This is important to avoid the performance
34 * runtime initialization process. 34 * overhead of the standard service loader mechanism for services loaded in the runtime
35 * initialization process.
35 */ 36 */
36 public class Services { 37 public class Services {
37 38
38 private static final ClassValue<List<Service>> cache = new ClassValue<List<Service>>() { 39 private static final ClassValue<List<Service>> cache = new ClassValue<List<Service>>() {
39 @Override 40 @Override
52 * Gets an {@link Iterable} of the implementations available for a given service. 53 * Gets an {@link Iterable} of the implementations available for a given service.
53 */ 54 */
54 @SuppressWarnings("unchecked") 55 @SuppressWarnings("unchecked")
55 @CallerSensitive 56 @CallerSensitive
56 public static <S> Iterable<S> load(Class<S> service) { 57 public static <S> Iterable<S> load(Class<S> service) {
58 // TODO(ds): add SecurityManager checks
57 if (Service.class.isAssignableFrom(service)) { 59 if (Service.class.isAssignableFrom(service)) {
58 try { 60 try {
59 return (Iterable<S>) cache.get(service); 61 return (Iterable<S>) cache.get(service);
60 } catch (UnsatisfiedLinkError e) { 62 } catch (UnsatisfiedLinkError e) {
61 // Fall back to standard ServiceLoader 63 // Fall back to standard ServiceLoader
65 // Need to use the ClassLoader of the caller 67 // Need to use the ClassLoader of the caller
66 ClassLoader cl = Reflection.getCallerClass().getClassLoader(); 68 ClassLoader cl = Reflection.getCallerClass().getClassLoader();
67 return ServiceLoader.load(service, cl); 69 return ServiceLoader.load(service, cl);
68 } 70 }
69 71
72 /**
73 * Gets the implementation for a given service for which at most one implementation must be
74 * available.
75 *
76 * @param service the service whose implementation is being requested
77 * @param required specifies if an {@link InternalError} should be thrown if no implementation
78 * of {@code service} is available
79 */
80 @SuppressWarnings("unchecked")
81 @CallerSensitive
82 public static <S> S loadSingle(Class<S> service, boolean required) {
83 // TODO(ds): add SecurityManager checks
84 Iterable<S> impls = null;
85 if (Service.class.isAssignableFrom(service)) {
86 try {
87 impls = (Iterable<S>) cache.get(service);
88 } catch (UnsatisfiedLinkError e) {
89 // Fall back to standard ServiceLoader
90 }
91 }
92
93 if (impls == null) {
94 // Need to use the ClassLoader of the caller
95 ClassLoader cl = Reflection.getCallerClass().getClassLoader();
96 impls = ServiceLoader.load(service, cl);
97 }
98 S singleImpl = null;
99 for (S impl : impls) {
100 if (singleImpl != null) {
101 throw new InternalError(String.format("Multiple %s implementations found: %s, %s", service.getName(), singleImpl.getClass().getName(), impl.getClass().getName()));
102 }
103 singleImpl = impl;
104 }
105 if (singleImpl == null && required) {
106 String javaHome = System.getProperty("java.home");
107 String vmName = System.getProperty("java.vm.name");
108 Formatter errorMessage = new Formatter();
109 errorMessage.format("The VM does not expose required service %s.%n", service.getName());
110 errorMessage.format("Currently used Java home directory is %s.%n", javaHome);
111 errorMessage.format("Currently used VM configuration is: %s", vmName);
112 throw new UnsupportedOperationException(errorMessage.toString());
113 }
114 return singleImpl;
115 }
116
70 private static native <S> S[] getServiceImpls(Class<?> service); 117 private static native <S> S[] getServiceImpls(Class<?> service);
71 } 118 }