Mercurial > hg > truffle
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 } |