Skip to content

Commit 8ec5893

Browse files
author
Doug Simon
committed
8346781: [JVMCI] Limit ServiceLoader to class initializers
Reviewed-by: never, yzheng
1 parent 3f0c137 commit 8ec5893

File tree

7 files changed

+40
-156
lines changed

7 files changed

+40
-156
lines changed

src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/Cleaner.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
* referenced by this might be referenced by {@link ResolvedJavaType} which is kept alive by a
3737
* {@link WeakReference} so we need equivalent reference strength.
3838
*/
39-
abstract class Cleaner extends WeakReference<Object> {
39+
public abstract class Cleaner extends WeakReference<Object> {
4040

4141
/**
4242
* Head of linked list of cleaners.
@@ -107,7 +107,7 @@ private static synchronized void remove(Cleaner cl) {
107107
/**
108108
* Remove the cleaners whose referents have become weakly reachable.
109109
*/
110-
static void clean() {
110+
public static void clean() {
111111
Cleaner c = (Cleaner) queue.poll();
112112
boolean oopHandleCleared = false;
113113
while (c != null) {

src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java

Lines changed: 19 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323
package jdk.vm.ci.hotspot;
2424

2525
import static jdk.vm.ci.common.InitTimer.timer;
26-
import static jdk.vm.ci.services.Services.IS_BUILDING_NATIVE_IMAGE;
2726
import static jdk.vm.ci.services.Services.IS_IN_NATIVE_IMAGE;
2827

2928
import java.io.IOException;
@@ -453,33 +452,26 @@ static void parse(HotSpotJVMCIRuntime runtime) {
453452
}
454453
}
455454

456-
private static HotSpotJVMCIBackendFactory findFactory(String architecture) {
457-
Iterable<HotSpotJVMCIBackendFactory> factories = getHotSpotJVMCIBackendFactories();
458-
assert factories != null : "sanity";
459-
for (HotSpotJVMCIBackendFactory factory : factories) {
460-
if (factory.getArchitecture().equalsIgnoreCase(architecture)) {
461-
return factory;
455+
/**
456+
* The backend factory for the JVMCI shared library.
457+
*/
458+
private static final HotSpotJVMCIBackendFactory backendFactory;
459+
static {
460+
String arch = HotSpotVMConfig.getHostArchitectureName();
461+
HotSpotJVMCIBackendFactory selected = null;
462+
for (HotSpotJVMCIBackendFactory factory : ServiceLoader.load(HotSpotJVMCIBackendFactory.class)) {
463+
if (factory.getArchitecture().equalsIgnoreCase(arch)) {
464+
if (selected != null) {
465+
throw new JVMCIError("Multiple factories available for %s: %s and %s",
466+
arch, selected, factory);
467+
}
468+
selected = factory;
462469
}
463470
}
464-
465-
throw new JVMCIError("No JVMCI runtime available for the %s architecture", architecture);
466-
}
467-
468-
private static volatile List<HotSpotJVMCIBackendFactory> cachedHotSpotJVMCIBackendFactories;
469-
470-
@SuppressFBWarnings(value = "LI_LAZY_INIT_UPDATE_STATIC", justification = "not sure about this")
471-
private static Iterable<HotSpotJVMCIBackendFactory> getHotSpotJVMCIBackendFactories() {
472-
if (IS_IN_NATIVE_IMAGE || cachedHotSpotJVMCIBackendFactories != null) {
473-
return cachedHotSpotJVMCIBackendFactories;
471+
if (selected == null) {
472+
throw new JVMCIError("No JVMCI runtime available for the %s architecture", arch);
474473
}
475-
Iterable<HotSpotJVMCIBackendFactory> result = ServiceLoader.load(HotSpotJVMCIBackendFactory.class, ClassLoader.getSystemClassLoader());
476-
if (IS_BUILDING_NATIVE_IMAGE) {
477-
cachedHotSpotJVMCIBackendFactories = new ArrayList<>();
478-
for (HotSpotJVMCIBackendFactory factory : result) {
479-
cachedHotSpotJVMCIBackendFactories.add(factory);
480-
}
481-
}
482-
return result;
474+
backendFactory = selected;
483475
}
484476

485477
/**
@@ -587,15 +579,8 @@ private HotSpotJVMCIRuntime() {
587579
// Initialize the Option values.
588580
Option.parse(this);
589581

590-
String hostArchitecture = config.getHostArchitectureName();
591-
592-
HotSpotJVMCIBackendFactory factory;
593-
try (InitTimer t = timer("find factory:", hostArchitecture)) {
594-
factory = findFactory(hostArchitecture);
595-
}
596-
597-
try (InitTimer t = timer("create JVMCI backend:", hostArchitecture)) {
598-
hostBackend = registerBackend(factory.createJVMCIBackend(this, null));
582+
try (InitTimer t = timer("create JVMCI backend:", backendFactory.getArchitecture())) {
583+
hostBackend = registerBackend(backendFactory.createJVMCIBackend(this, null));
599584
}
600585

601586
compilerFactory = HotSpotJVMCICompilerConfig.getCompilerFactory(this);

src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotVMConfig.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ static HotSpotVMConfig config() {
5555
* Gets the host architecture name for the purpose of finding the corresponding
5656
* {@linkplain HotSpotJVMCIBackendFactory backend}.
5757
*/
58-
String getHostArchitectureName() {
58+
static String getHostArchitectureName() {
5959
Architecture arch = Architecture.current();
6060
switch (arch) {
6161
case X64: return "amd64";

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

Lines changed: 7 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,6 @@
2222
*/
2323
package jdk.vm.ci.services;
2424

25-
import static jdk.vm.ci.services.Services.IS_BUILDING_NATIVE_IMAGE;
26-
2725
import java.util.ArrayList;
2826
import java.util.List;
2927
import java.util.ServiceLoader;
@@ -71,24 +69,12 @@ protected JVMCIServiceLocator() {
7169
*/
7270
protected abstract <S> S getProvider(Class<S> service);
7371

74-
private static volatile List<JVMCIServiceLocator> cachedLocators;
75-
76-
private static Iterable<JVMCIServiceLocator> getJVMCIServiceLocators() {
77-
Iterable<JVMCIServiceLocator> result = cachedLocators;
78-
if (result != null) {
79-
return result;
80-
}
81-
result = ServiceLoader.load(JVMCIServiceLocator.class, ClassLoader.getSystemClassLoader());
82-
if (IS_BUILDING_NATIVE_IMAGE) {
83-
ArrayList<JVMCIServiceLocator> l = new ArrayList<>();
84-
for (JVMCIServiceLocator locator : result) {
85-
l.add(locator);
86-
}
87-
l.trimToSize();
88-
cachedLocators = l;
89-
return l;
90-
}
91-
return result;
72+
/**
73+
* The available set of locators.
74+
*/
75+
private static final List<JVMCIServiceLocator> locators = new ArrayList<>();
76+
static {
77+
ServiceLoader.load(JVMCIServiceLocator.class).forEach(locators::add);
9278
}
9379

9480
/**
@@ -106,7 +92,7 @@ public static <S> List<S> getProviders(Class<S> service) {
10692
sm.checkPermission(new JVMCIPermission());
10793
}
10894
List<S> providers = new ArrayList<>();
109-
for (JVMCIServiceLocator access : getJVMCIServiceLocators()) {
95+
for (JVMCIServiceLocator access : locators) {
11096
S provider = access.getProvider(service);
11197
if (provider != null) {
11298
providers.add(provider);

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

Lines changed: 0 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,10 @@
2222
*/
2323
package jdk.vm.ci.services;
2424

25-
import java.util.ArrayList;
26-
import java.util.Formatter;
2725
import java.util.HashMap;
2826
import java.util.List;
2927
import java.util.Map;
3028
import java.util.Objects;
31-
import java.util.ServiceLoader;
3229
import java.util.Set;
3330
import java.util.function.Consumer;
3431
import java.util.function.Supplier;
@@ -44,13 +41,6 @@
4441
*/
4542
public final class Services {
4643

47-
/**
48-
* Guards code that should be run when building an JVMCI shared library but should be excluded
49-
* from (being compiled into) the library. Such code must be directly guarded by an {@code if}
50-
* statement on this field - the guard cannot be behind a method call.
51-
*/
52-
public static final boolean IS_BUILDING_NATIVE_IMAGE = Boolean.parseBoolean(VM.getSavedProperty("jdk.vm.ci.services.aot"));
53-
5444
/**
5545
* Guards code that should only be run in a JVMCI shared library. Such code must be directly
5646
* guarded by an {@code if} statement on this field - the guard cannot be behind a method call.
@@ -131,34 +121,6 @@ public static void initializeJVMCI() {
131121
}
132122
}
133123

134-
private static final Map<Class<?>, List<?>> servicesCache = IS_BUILDING_NATIVE_IMAGE ? new HashMap<>() : null;
135-
136-
@SuppressWarnings("unchecked")
137-
private static <S> Iterable<S> load0(Class<S> service) {
138-
if (IS_IN_NATIVE_IMAGE || IS_BUILDING_NATIVE_IMAGE) {
139-
List<?> list = servicesCache.get(service);
140-
if (list != null) {
141-
return (Iterable<S>) list;
142-
}
143-
if (IS_IN_NATIVE_IMAGE) {
144-
throw new InternalError(String.format("No %s providers found when building native image", service.getName()));
145-
}
146-
}
147-
148-
Iterable<S> providers = ServiceLoader.load(service, ClassLoader.getSystemClassLoader());
149-
if (IS_BUILDING_NATIVE_IMAGE) {
150-
synchronized (servicesCache) {
151-
ArrayList<S> providersList = new ArrayList<>();
152-
for (S provider : providers) {
153-
providersList.add(provider);
154-
}
155-
servicesCache.put(service, providersList);
156-
providers = providersList;
157-
}
158-
}
159-
return providers;
160-
}
161-
162124
/**
163125
* Opens all JVMCI packages to {@code otherModule}.
164126
*/
@@ -175,57 +137,6 @@ static void openJVMCITo(Module otherModule) {
175137
}
176138
}
177139

178-
/**
179-
* Gets an {@link Iterable} of the JVMCI providers available for a given service.
180-
*
181-
* @throws SecurityException if a security manager is present and it denies <tt>
182-
* {@link RuntimePermission}("jvmci")</tt>
183-
*/
184-
public static <S> Iterable<S> load(Class<S> service) {
185-
@SuppressWarnings("removal")
186-
SecurityManager sm = System.getSecurityManager();
187-
if (sm != null) {
188-
sm.checkPermission(new JVMCIPermission());
189-
}
190-
return load0(service);
191-
}
192-
193-
/**
194-
* Gets the JVMCI provider for a given service for which at most one provider must be available.
195-
*
196-
* @param service the service whose provider is being requested
197-
* @param required specifies if an {@link InternalError} should be thrown if no provider of
198-
* {@code service} is available
199-
* @throws SecurityException if a security manager is present and it denies <tt>
200-
* {@link RuntimePermission}("jvmci")</tt>
201-
*/
202-
public static <S> S loadSingle(Class<S> service, boolean required) {
203-
@SuppressWarnings("removal")
204-
SecurityManager sm = System.getSecurityManager();
205-
if (sm != null) {
206-
sm.checkPermission(new JVMCIPermission());
207-
}
208-
Iterable<S> providers = load0(service);
209-
210-
S singleProvider = null;
211-
for (S provider : providers) {
212-
if (singleProvider != null) {
213-
throw new InternalError(String.format("Multiple %s providers found: %s, %s", service.getName(), singleProvider.getClass().getName(), provider.getClass().getName()));
214-
}
215-
singleProvider = provider;
216-
}
217-
if (singleProvider == null && required) {
218-
String javaHome = Services.getSavedProperty("java.home");
219-
String vmName = Services.getSavedProperty("java.vm.name");
220-
Formatter errorMessage = new Formatter();
221-
errorMessage.format("The VM does not expose required service %s.%n", service.getName());
222-
errorMessage.format("Currently used Java home directory is %s.%n", javaHome);
223-
errorMessage.format("Currently used VM configuration is: %s", vmName);
224-
throw new UnsupportedOperationException(errorMessage.toString());
225-
}
226-
return singleProvider;
227-
}
228-
229140
/**
230141
* Creates a thread-local variable that notifies {@code onThreadTermination} when a thread
231142
* terminates and it has been initialized in the terminating thread (even if it was initialized

test/hotspot/jtreg/compiler/jvmci/events/JvmciShutdownEventListener.java

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,13 @@ public class JvmciShutdownEventListener extends JVMCIServiceLocator implements H
3131
public static final String MESSAGE = "Shutdown notified";
3232
public static final String GOT_INTERNAL_ERROR = "Got internal error";
3333

34-
public static void main(String args[]) {
35-
try {
36-
HotSpotJVMCIRuntime.runtime(); // let's trigger that lazy jvmci init
37-
} catch (Error e) {
38-
System.out.println(GOT_INTERNAL_ERROR);
34+
public static class Main {
35+
public static void main(String args[]) {
36+
try {
37+
HotSpotJVMCIRuntime.runtime(); // let's trigger that lazy jvmci init
38+
} catch (Error e) {
39+
System.out.println(GOT_INTERNAL_ERROR);
40+
}
3941
}
4042
}
4143

test/hotspot/jtreg/compiler/jvmci/events/JvmciShutdownEventTest.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,11 +53,11 @@
5353
import jdk.test.lib.cli.CommandLineOptionTest;
5454

5555
public class JvmciShutdownEventTest {
56-
private final static String[] MESSAGE = new String[]{
56+
private final static String[] MESSAGE = {
5757
JvmciShutdownEventListener.MESSAGE
5858
};
5959

60-
private final static String[] ERROR_MESSAGE = new String[]{
60+
private final static String[] ERROR_MESSAGE = {
6161
JvmciShutdownEventListener.GOT_INTERNAL_ERROR
6262
};
6363

@@ -68,15 +68,15 @@ public static void main(String args[]) throws Throwable {
6868
"Unexpected output with +EnableJVMCI", ExitCode.OK,
6969
addTestVMOptions, "-XX:+UnlockExperimentalVMOptions",
7070
"-XX:+EnableJVMCI", "-XX:-UseJVMCICompiler", "-Xbootclasspath/a:.",
71-
JvmciShutdownEventListener.class.getName()
71+
JvmciShutdownEventListener.Main.class.getName()
7272
);
7373

7474
CommandLineOptionTest.verifyJVMStartup(ERROR_MESSAGE, MESSAGE,
7575
"Unexpected exit code with -EnableJVMCI",
7676
"Unexpected output with -EnableJVMCI", ExitCode.OK,
7777
addTestVMOptions, "-XX:+UnlockExperimentalVMOptions",
7878
"-XX:-EnableJVMCI", "-XX:-UseJVMCICompiler", "-Xbootclasspath/a:.",
79-
JvmciShutdownEventListener.class.getName()
79+
JvmciShutdownEventListener.Main.class.getName()
8080
);
8181
}
8282
}

0 commit comments

Comments
 (0)