mirror of
https://github.com/openjdk/jdk.git
synced 2026-07-20 16:09:21 +00:00
8346781: [JVMCI] Limit ServiceLoader to class initializers
Reviewed-by: never, yzheng
This commit is contained in:
parent
3f0c137026
commit
8ec589390f
@ -36,7 +36,7 @@ import jdk.vm.ci.meta.ResolvedJavaType;
|
||||
* referenced by this might be referenced by {@link ResolvedJavaType} which is kept alive by a
|
||||
* {@link WeakReference} so we need equivalent reference strength.
|
||||
*/
|
||||
abstract class Cleaner extends WeakReference<Object> {
|
||||
public abstract class Cleaner extends WeakReference<Object> {
|
||||
|
||||
/**
|
||||
* Head of linked list of cleaners.
|
||||
@ -107,7 +107,7 @@ abstract class Cleaner extends WeakReference<Object> {
|
||||
/**
|
||||
* Remove the cleaners whose referents have become weakly reachable.
|
||||
*/
|
||||
static void clean() {
|
||||
public static void clean() {
|
||||
Cleaner c = (Cleaner) queue.poll();
|
||||
boolean oopHandleCleared = false;
|
||||
while (c != null) {
|
||||
|
||||
@ -23,7 +23,6 @@
|
||||
package jdk.vm.ci.hotspot;
|
||||
|
||||
import static jdk.vm.ci.common.InitTimer.timer;
|
||||
import static jdk.vm.ci.services.Services.IS_BUILDING_NATIVE_IMAGE;
|
||||
import static jdk.vm.ci.services.Services.IS_IN_NATIVE_IMAGE;
|
||||
|
||||
import java.io.IOException;
|
||||
@ -453,33 +452,26 @@ public final class HotSpotJVMCIRuntime implements JVMCIRuntime {
|
||||
}
|
||||
}
|
||||
|
||||
private static HotSpotJVMCIBackendFactory findFactory(String architecture) {
|
||||
Iterable<HotSpotJVMCIBackendFactory> factories = getHotSpotJVMCIBackendFactories();
|
||||
assert factories != null : "sanity";
|
||||
for (HotSpotJVMCIBackendFactory factory : factories) {
|
||||
if (factory.getArchitecture().equalsIgnoreCase(architecture)) {
|
||||
return factory;
|
||||
/**
|
||||
* The backend factory for the JVMCI shared library.
|
||||
*/
|
||||
private static final HotSpotJVMCIBackendFactory backendFactory;
|
||||
static {
|
||||
String arch = HotSpotVMConfig.getHostArchitectureName();
|
||||
HotSpotJVMCIBackendFactory selected = null;
|
||||
for (HotSpotJVMCIBackendFactory factory : ServiceLoader.load(HotSpotJVMCIBackendFactory.class)) {
|
||||
if (factory.getArchitecture().equalsIgnoreCase(arch)) {
|
||||
if (selected != null) {
|
||||
throw new JVMCIError("Multiple factories available for %s: %s and %s",
|
||||
arch, selected, factory);
|
||||
}
|
||||
selected = factory;
|
||||
}
|
||||
}
|
||||
|
||||
throw new JVMCIError("No JVMCI runtime available for the %s architecture", architecture);
|
||||
}
|
||||
|
||||
private static volatile List<HotSpotJVMCIBackendFactory> cachedHotSpotJVMCIBackendFactories;
|
||||
|
||||
@SuppressFBWarnings(value = "LI_LAZY_INIT_UPDATE_STATIC", justification = "not sure about this")
|
||||
private static Iterable<HotSpotJVMCIBackendFactory> getHotSpotJVMCIBackendFactories() {
|
||||
if (IS_IN_NATIVE_IMAGE || cachedHotSpotJVMCIBackendFactories != null) {
|
||||
return cachedHotSpotJVMCIBackendFactories;
|
||||
if (selected == null) {
|
||||
throw new JVMCIError("No JVMCI runtime available for the %s architecture", arch);
|
||||
}
|
||||
Iterable<HotSpotJVMCIBackendFactory> result = ServiceLoader.load(HotSpotJVMCIBackendFactory.class, ClassLoader.getSystemClassLoader());
|
||||
if (IS_BUILDING_NATIVE_IMAGE) {
|
||||
cachedHotSpotJVMCIBackendFactories = new ArrayList<>();
|
||||
for (HotSpotJVMCIBackendFactory factory : result) {
|
||||
cachedHotSpotJVMCIBackendFactories.add(factory);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
backendFactory = selected;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -587,15 +579,8 @@ public final class HotSpotJVMCIRuntime implements JVMCIRuntime {
|
||||
// Initialize the Option values.
|
||||
Option.parse(this);
|
||||
|
||||
String hostArchitecture = config.getHostArchitectureName();
|
||||
|
||||
HotSpotJVMCIBackendFactory factory;
|
||||
try (InitTimer t = timer("find factory:", hostArchitecture)) {
|
||||
factory = findFactory(hostArchitecture);
|
||||
}
|
||||
|
||||
try (InitTimer t = timer("create JVMCI backend:", hostArchitecture)) {
|
||||
hostBackend = registerBackend(factory.createJVMCIBackend(this, null));
|
||||
try (InitTimer t = timer("create JVMCI backend:", backendFactory.getArchitecture())) {
|
||||
hostBackend = registerBackend(backendFactory.createJVMCIBackend(this, null));
|
||||
}
|
||||
|
||||
compilerFactory = HotSpotJVMCICompilerConfig.getCompilerFactory(this);
|
||||
|
||||
@ -55,7 +55,7 @@ class HotSpotVMConfig extends HotSpotVMConfigAccess {
|
||||
* Gets the host architecture name for the purpose of finding the corresponding
|
||||
* {@linkplain HotSpotJVMCIBackendFactory backend}.
|
||||
*/
|
||||
String getHostArchitectureName() {
|
||||
static String getHostArchitectureName() {
|
||||
Architecture arch = Architecture.current();
|
||||
switch (arch) {
|
||||
case X64: return "amd64";
|
||||
|
||||
@ -22,8 +22,6 @@
|
||||
*/
|
||||
package jdk.vm.ci.services;
|
||||
|
||||
import static jdk.vm.ci.services.Services.IS_BUILDING_NATIVE_IMAGE;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.ServiceLoader;
|
||||
@ -71,24 +69,12 @@ public abstract class JVMCIServiceLocator {
|
||||
*/
|
||||
protected abstract <S> S getProvider(Class<S> service);
|
||||
|
||||
private static volatile List<JVMCIServiceLocator> cachedLocators;
|
||||
|
||||
private static Iterable<JVMCIServiceLocator> getJVMCIServiceLocators() {
|
||||
Iterable<JVMCIServiceLocator> result = cachedLocators;
|
||||
if (result != null) {
|
||||
return result;
|
||||
}
|
||||
result = ServiceLoader.load(JVMCIServiceLocator.class, ClassLoader.getSystemClassLoader());
|
||||
if (IS_BUILDING_NATIVE_IMAGE) {
|
||||
ArrayList<JVMCIServiceLocator> l = new ArrayList<>();
|
||||
for (JVMCIServiceLocator locator : result) {
|
||||
l.add(locator);
|
||||
}
|
||||
l.trimToSize();
|
||||
cachedLocators = l;
|
||||
return l;
|
||||
}
|
||||
return result;
|
||||
/**
|
||||
* The available set of locators.
|
||||
*/
|
||||
private static final List<JVMCIServiceLocator> locators = new ArrayList<>();
|
||||
static {
|
||||
ServiceLoader.load(JVMCIServiceLocator.class).forEach(locators::add);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -106,7 +92,7 @@ public abstract class JVMCIServiceLocator {
|
||||
sm.checkPermission(new JVMCIPermission());
|
||||
}
|
||||
List<S> providers = new ArrayList<>();
|
||||
for (JVMCIServiceLocator access : getJVMCIServiceLocators()) {
|
||||
for (JVMCIServiceLocator access : locators) {
|
||||
S provider = access.getProvider(service);
|
||||
if (provider != null) {
|
||||
providers.add(provider);
|
||||
|
||||
@ -22,13 +22,10 @@
|
||||
*/
|
||||
package jdk.vm.ci.services;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Formatter;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.ServiceLoader;
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
@ -44,13 +41,6 @@ import jdk.internal.util.OperatingSystem;
|
||||
*/
|
||||
public final class Services {
|
||||
|
||||
/**
|
||||
* Guards code that should be run when building an JVMCI shared library but should be excluded
|
||||
* from (being compiled into) the library. Such code must be directly guarded by an {@code if}
|
||||
* statement on this field - the guard cannot be behind a method call.
|
||||
*/
|
||||
public static final boolean IS_BUILDING_NATIVE_IMAGE = Boolean.parseBoolean(VM.getSavedProperty("jdk.vm.ci.services.aot"));
|
||||
|
||||
/**
|
||||
* Guards code that should only be run in a JVMCI shared library. Such code must be directly
|
||||
* guarded by an {@code if} statement on this field - the guard cannot be behind a method call.
|
||||
@ -131,34 +121,6 @@ public final class Services {
|
||||
}
|
||||
}
|
||||
|
||||
private static final Map<Class<?>, List<?>> servicesCache = IS_BUILDING_NATIVE_IMAGE ? new HashMap<>() : null;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static <S> Iterable<S> load0(Class<S> service) {
|
||||
if (IS_IN_NATIVE_IMAGE || IS_BUILDING_NATIVE_IMAGE) {
|
||||
List<?> list = servicesCache.get(service);
|
||||
if (list != null) {
|
||||
return (Iterable<S>) list;
|
||||
}
|
||||
if (IS_IN_NATIVE_IMAGE) {
|
||||
throw new InternalError(String.format("No %s providers found when building native image", service.getName()));
|
||||
}
|
||||
}
|
||||
|
||||
Iterable<S> providers = ServiceLoader.load(service, ClassLoader.getSystemClassLoader());
|
||||
if (IS_BUILDING_NATIVE_IMAGE) {
|
||||
synchronized (servicesCache) {
|
||||
ArrayList<S> providersList = new ArrayList<>();
|
||||
for (S provider : providers) {
|
||||
providersList.add(provider);
|
||||
}
|
||||
servicesCache.put(service, providersList);
|
||||
providers = providersList;
|
||||
}
|
||||
}
|
||||
return providers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens all JVMCI packages to {@code otherModule}.
|
||||
*/
|
||||
@ -175,57 +137,6 @@ public final class Services {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an {@link Iterable} of the JVMCI providers available for a given service.
|
||||
*
|
||||
* @throws SecurityException if a security manager is present and it denies <tt>
|
||||
* {@link RuntimePermission}("jvmci")</tt>
|
||||
*/
|
||||
public static <S> Iterable<S> load(Class<S> service) {
|
||||
@SuppressWarnings("removal")
|
||||
SecurityManager sm = System.getSecurityManager();
|
||||
if (sm != null) {
|
||||
sm.checkPermission(new JVMCIPermission());
|
||||
}
|
||||
return load0(service);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 <tt>
|
||||
* {@link RuntimePermission}("jvmci")</tt>
|
||||
*/
|
||||
public static <S> S loadSingle(Class<S> service, boolean required) {
|
||||
@SuppressWarnings("removal")
|
||||
SecurityManager sm = System.getSecurityManager();
|
||||
if (sm != null) {
|
||||
sm.checkPermission(new JVMCIPermission());
|
||||
}
|
||||
Iterable<S> providers = load0(service);
|
||||
|
||||
S singleProvider = null;
|
||||
for (S provider : providers) {
|
||||
if (singleProvider != null) {
|
||||
throw new InternalError(String.format("Multiple %s providers found: %s, %s", service.getName(), singleProvider.getClass().getName(), provider.getClass().getName()));
|
||||
}
|
||||
singleProvider = provider;
|
||||
}
|
||||
if (singleProvider == null && required) {
|
||||
String javaHome = Services.getSavedProperty("java.home");
|
||||
String vmName = Services.getSavedProperty("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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a thread-local variable that notifies {@code onThreadTermination} when a thread
|
||||
* terminates and it has been initialized in the terminating thread (even if it was initialized
|
||||
|
||||
@ -31,11 +31,13 @@ public class JvmciShutdownEventListener extends JVMCIServiceLocator implements H
|
||||
public static final String MESSAGE = "Shutdown notified";
|
||||
public static final String GOT_INTERNAL_ERROR = "Got internal error";
|
||||
|
||||
public static void main(String args[]) {
|
||||
try {
|
||||
HotSpotJVMCIRuntime.runtime(); // let's trigger that lazy jvmci init
|
||||
} catch (Error e) {
|
||||
System.out.println(GOT_INTERNAL_ERROR);
|
||||
public static class Main {
|
||||
public static void main(String args[]) {
|
||||
try {
|
||||
HotSpotJVMCIRuntime.runtime(); // let's trigger that lazy jvmci init
|
||||
} catch (Error e) {
|
||||
System.out.println(GOT_INTERNAL_ERROR);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -53,11 +53,11 @@ import jdk.test.lib.process.ExitCode;
|
||||
import jdk.test.lib.cli.CommandLineOptionTest;
|
||||
|
||||
public class JvmciShutdownEventTest {
|
||||
private final static String[] MESSAGE = new String[]{
|
||||
private final static String[] MESSAGE = {
|
||||
JvmciShutdownEventListener.MESSAGE
|
||||
};
|
||||
|
||||
private final static String[] ERROR_MESSAGE = new String[]{
|
||||
private final static String[] ERROR_MESSAGE = {
|
||||
JvmciShutdownEventListener.GOT_INTERNAL_ERROR
|
||||
};
|
||||
|
||||
@ -68,7 +68,7 @@ public class JvmciShutdownEventTest {
|
||||
"Unexpected output with +EnableJVMCI", ExitCode.OK,
|
||||
addTestVMOptions, "-XX:+UnlockExperimentalVMOptions",
|
||||
"-XX:+EnableJVMCI", "-XX:-UseJVMCICompiler", "-Xbootclasspath/a:.",
|
||||
JvmciShutdownEventListener.class.getName()
|
||||
JvmciShutdownEventListener.Main.class.getName()
|
||||
);
|
||||
|
||||
CommandLineOptionTest.verifyJVMStartup(ERROR_MESSAGE, MESSAGE,
|
||||
@ -76,7 +76,7 @@ public class JvmciShutdownEventTest {
|
||||
"Unexpected output with -EnableJVMCI", ExitCode.OK,
|
||||
addTestVMOptions, "-XX:+UnlockExperimentalVMOptions",
|
||||
"-XX:-EnableJVMCI", "-XX:-UseJVMCICompiler", "-Xbootclasspath/a:.",
|
||||
JvmciShutdownEventListener.class.getName()
|
||||
JvmciShutdownEventListener.Main.class.getName()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user