De-couple ServiceLoader calls from class loading

Use the holder pattern to de-couple the loading of super classes from
the ServiceLoader calls to set up global instances. This prevents
potential lock inversions.

Bug: 579550
Change-Id: Ie8284e4d6d680ddd4cc6a486bbefe8ed00266240
Signed-off-by: Thomas Wolf <thomas.wolf@paranor.ch>
This commit is contained in:
Thomas Wolf 2022-04-03 21:06:57 +02:00
parent 7e06e51750
commit 7f9cd7d2ba
2 changed files with 65 additions and 28 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2021, Thomas Wolf <thomas.wolf@paranor.ch> and others
* Copyright (C) 2021, 2022 Thomas Wolf <thomas.wolf@paranor.ch> and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Distribution License v. 1.0 which is available at
@ -26,20 +26,41 @@ public abstract class GpgSignatureVerifierFactory {
private static final Logger LOG = LoggerFactory
.getLogger(GpgSignatureVerifierFactory.class);
private static volatile GpgSignatureVerifierFactory defaultFactory = loadDefault();
private static class DefaultFactory {
private static GpgSignatureVerifierFactory loadDefault() {
try {
ServiceLoader<GpgSignatureVerifierFactory> loader = ServiceLoader
.load(GpgSignatureVerifierFactory.class);
Iterator<GpgSignatureVerifierFactory> iter = loader.iterator();
if (iter.hasNext()) {
return iter.next();
private static volatile GpgSignatureVerifierFactory defaultFactory = loadDefault();
private static GpgSignatureVerifierFactory loadDefault() {
try {
ServiceLoader<GpgSignatureVerifierFactory> loader = ServiceLoader
.load(GpgSignatureVerifierFactory.class);
Iterator<GpgSignatureVerifierFactory> iter = loader.iterator();
if (iter.hasNext()) {
return iter.next();
}
} catch (ServiceConfigurationError e) {
LOG.error(e.getMessage(), e);
}
} catch (ServiceConfigurationError e) {
LOG.error(e.getMessage(), e);
return null;
}
private DefaultFactory() {
// No instantiation
}
public static GpgSignatureVerifierFactory getDefault() {
return defaultFactory;
}
/**
* Sets the default factory.
*
* @param factory
* the new default factory
*/
public static void setDefault(GpgSignatureVerifierFactory factory) {
defaultFactory = factory;
}
return null;
}
/**
@ -48,7 +69,7 @@ private static GpgSignatureVerifierFactory loadDefault() {
* @return the default factory or {@code null} if none set
*/
public static GpgSignatureVerifierFactory getDefault() {
return defaultFactory;
return DefaultFactory.getDefault();
}
/**
@ -58,7 +79,7 @@ public static GpgSignatureVerifierFactory getDefault() {
* the new default factory
*/
public static void setDefault(GpgSignatureVerifierFactory factory) {
defaultFactory = factory;
DefaultFactory.setDefault(factory);
}
/**

View File

@ -1,6 +1,6 @@
/*
* Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com>
* Copyright (C) 2008, 2020 Shawn O. Pearce <spearce@spearce.org> and others
* Copyright (C) 2008, 2022 Shawn O. Pearce <spearce@spearce.org> and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Distribution License v. 1.0 which is available at
@ -36,15 +36,35 @@
*/
public abstract class SshSessionFactory {
private static volatile SshSessionFactory INSTANCE = loadSshSessionFactory();
private static class DefaultFactory {
private static SshSessionFactory loadSshSessionFactory() {
ServiceLoader<SshSessionFactory> loader = ServiceLoader.load(SshSessionFactory.class);
Iterator<SshSessionFactory> iter = loader.iterator();
if(iter.hasNext()) {
return iter.next();
private static volatile SshSessionFactory INSTANCE = loadSshSessionFactory();
private static SshSessionFactory loadSshSessionFactory() {
ServiceLoader<SshSessionFactory> loader = ServiceLoader
.load(SshSessionFactory.class);
Iterator<SshSessionFactory> iter = loader.iterator();
if (iter.hasNext()) {
return iter.next();
}
return null;
}
private DefaultFactory() {
// No instantiation
}
public static SshSessionFactory getInstance() {
return INSTANCE;
}
public static void setInstance(SshSessionFactory newFactory) {
if (newFactory != null) {
INSTANCE = newFactory;
} else {
INSTANCE = loadSshSessionFactory();
}
}
return null;
}
/**
@ -57,7 +77,7 @@ private static SshSessionFactory loadSshSessionFactory() {
* @return factory the current factory for this JVM.
*/
public static SshSessionFactory getInstance() {
return INSTANCE;
return DefaultFactory.getInstance();
}
/**
@ -68,11 +88,7 @@ public static SshSessionFactory getInstance() {
* {@code null} the default factory will be restored.
*/
public static void setInstance(SshSessionFactory newFactory) {
if (newFactory != null) {
INSTANCE = newFactory;
} else {
INSTANCE = loadSshSessionFactory();
}
DefaultFactory.setInstance(newFactory);
}
/**