Skip to content

Commit f60fb15

Browse files
authored
RATIS-1351. Fix classloader mismatch while using ratis by fat-jar (#454)
1 parent dc0b68b commit f60fb15

2 files changed

Lines changed: 33 additions & 4 deletions

File tree

ratis-common/src/main/java/org/apache/ratis/util/ReflectionUtils.java

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,19 @@ static ClassLoader getClassLoader() {
104104
* @return the class object, or null if it could not be found.
105105
*/
106106
static Class<?> getClassByNameOrNull(String name) {
107+
return getClassByNameOrNull(name, null);
108+
}
109+
110+
/**
111+
* Load a class by name through a specific classloader, returning null rather
112+
* than throwing an exception if it couldn't be loaded. This is to avoid the
113+
* overhead of creating an exception.
114+
*
115+
* @param name the class name
116+
* @param classLoader the classloader
117+
* @return the class object, or null if it could not be found.
118+
*/
119+
static Class<?> getClassByNameOrNull(String name, ClassLoader classLoader) {
107120
final Map<String, WeakReference<Class<?>>> map = Classes.getClassMap();
108121

109122
Class<?> clazz = null;
@@ -114,7 +127,8 @@ static Class<?> getClassByNameOrNull(String name) {
114127

115128
if (clazz == null) {
116129
try {
117-
clazz = Class.forName(name, true, Classes.CLASS_LOADER);
130+
clazz = Class.forName(name, true,
131+
classLoader != null ? classLoader : Classes.CLASS_LOADER);
118132
} catch (ClassNotFoundException e) {
119133
// Leave a marker that the class isn't found
120134
map.put(name, new WeakReference<>(Classes.NEGATIVE_CACHE_SENTINEL));
@@ -139,7 +153,20 @@ static Class<?> getClassByNameOrNull(String name) {
139153
* @throws ClassNotFoundException if the class is not found.
140154
*/
141155
static Class<?> getClassByName(String name) throws ClassNotFoundException {
142-
Class<?> ret = getClassByNameOrNull(name);
156+
return getClassByName(name, null);
157+
}
158+
159+
/**
160+
* Load a class by name through a specific classloader.
161+
*
162+
* @param name the class name.
163+
* @param classLoader the classloader.
164+
* @return the class object.
165+
* @throws ClassNotFoundException if the class is not found.
166+
*/
167+
static Class<?> getClassByName(String name, ClassLoader classLoader)
168+
throws ClassNotFoundException {
169+
Class<?> ret = getClassByNameOrNull(name, classLoader);
143170
if (ret == null) {
144171
throw new ClassNotFoundException("Class " + name + " not found");
145172
}
@@ -210,7 +237,7 @@ static <BASE> Class<? extends BASE> getImplClass(Class<BASE> base) {
210237

211238
static <BASE> Class<? extends BASE> getClass(String subClassName, Class<BASE> base) {
212239
try {
213-
return getClassByName(subClassName).asSubclass(base);
240+
return getClassByName(subClassName, base.getClassLoader()).asSubclass(base);
214241
} catch (ClassNotFoundException e) {
215242
throw new IllegalArgumentException("Failed to get class "
216243
+ subClassName + " as a subclass of " + base, e);

ratis-metrics/src/main/java/org/apache/ratis/metrics/MetricRegistriesLoader.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,9 @@ static MetricRegistries load(List<MetricRegistries> availableImplementations) {
8585
}
8686

8787
private static List<MetricRegistries> getDefinedImplemantations() {
88-
ServiceLoader<MetricRegistries> loader = ServiceLoader.load(MetricRegistries.class);
88+
ServiceLoader<MetricRegistries> loader = ServiceLoader.load(
89+
MetricRegistries.class,
90+
MetricRegistries.class.getClassLoader());
8991
List<MetricRegistries> availableFactories = new ArrayList<>();
9092
for (MetricRegistries impl : loader) {
9193
availableFactories.add(impl);

0 commit comments

Comments
 (0)